Added support for custom ui buttons and dialogs.

Ylian Saint-Hilaire committed Jun 1, 2020 at 17:26 UTC 8c0ae5bb5256bb6363f3cd616631946cb8dfec2c
10 files changed +100 -15
MeshCentralServer.njsproj
-2
@@ -61,9 +61,7 @@
61 <Compile Include="agents\modules_meshcore\amt-xml.js" />
62 <Compile Include="agents\modules_meshcore\amt.js" />
63 <Compile Include="agents\modules_meshcore\apfclient.js" />
64 - <Compile Include="agents\modules_meshcore\identifiers.js" />
64 <Compile Include="agents\modules_meshcore\monitor-border.js" />
66 - <Compile Include="agents\modules_meshcore\power-monitor.js" />
65 <Compile Include="agents\modules_meshcore\smbios.js" />
66 <Compile Include="agents\modules_meshcore\sysinfo.js" />
67 <Compile Include="agents\modules_meshcore\wifi-scanner-windows.js" />
agents/MeshCmd-signed.exe
Binary files a/agents/MeshCmd-signed.exe and b/agents/MeshCmd-signed.exe differ
agents/MeshCmd64-signed.exe
Binary files a/agents/MeshCmd64-signed.exe and b/agents/MeshCmd64-signed.exe differ
agents/MeshService-signed.exe
Binary files a/agents/MeshService-signed.exe and b/agents/MeshService-signed.exe differ
agents/MeshService64-signed.exe
Binary files a/agents/MeshService64-signed.exe and b/agents/MeshService64-signed.exe differ
agents/modules_meshcmd/amt-mei.js
+3 -9
@@ -27,7 +27,6 @@ function amt_heci() {
27 this._setupPTHI = function _setupPTHI()
28 {
29 this._amt = heci.create();
30 - this._amt.descriptorMetadata = "amt-pthi";
30 this._amt.BiosVersionLen = 65;
31 this._amt.UnicodeStringLen = 20;
32
@@ -398,25 +397,20 @@ function amt_heci() {
397 fn.apply(this, opt);
398 }, callback, optional);
399 }
401 - this.getProtocolVersion = function getProtocolVersion(callback)
402 - {
400 + this.getProtocolVersion = function getProtocolVersion(callback) {
401 var optional = [];
402 for (var i = 1; i < arguments.length; ++i) { opt.push(arguments[i]); }
403
406 - if (!this._tmpSession) { this._tmpSession = heci.create(); this._tmpSession.parent = this;}
407 - this._tmpSession.doIoctl(heci.IOCTL.HECI_VERSION, Buffer.alloc(5), Buffer.alloc(5), function (status, buffer, self, fn, opt)
408 - {
404 + heci.doIoctl(heci.IOCTL.HECI_VERSION, Buffer.alloc(5), Buffer.alloc(5), function (status, buffer, self, fn, opt) {
405 if (status == 0) {
406 var result = buffer.readUInt8(0).toString() + '.' + buffer.readUInt8(1).toString() + '.' + buffer.readUInt8(2).toString() + '.' + buffer.readUInt16BE(3).toString();
407 opt.unshift(result);
408 fn.apply(self, opt);
409 }
414 - else
415 - {
410 + else {
411 opt.unshift(null);
412 fn.apply(self, opt);
413 }
419 -
414 }, this, callback, optional);
415 }
416 }
meshuser.js
+9
@@ -4323,6 +4323,15 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
4323 }
4324 break;
4325 }
4326 + case 'uicustomevent': {
4327 + // Event the change
4328 + var message = { etype: 'user', userid: user._id, username: user.name, action: 'uicustomevent', domain: domain.id, nolog: 1, uisection: command.section, element: command.element };
4329 + if (command.selectedDevices != null) { message.selectedDevices = command.selectedDevices; }
4330 + if (command.src != null) { message.src = command.src; }
4331 + if (command.values != null) { message.values = command.values; }
4332 + parent.parent.DispatchEvent(['*', user._id], obj, message);
4333 + break;
4334 + }
4335 default: {
4336 // Unknown user action
4337 console.log('Unknown action from user ' + user.name + ': ' + command.action + '.');
public/commander.htm
+1 -1
@@ -927,7 +927,7 @@ new FileReader;a.onloadend=function(){var b=a.result;G.location.href="data:attac
927 function(b){G.location.href=a.toURL();h.readyState=h.DONE;n(h,"writeend",b);r(a)};b.onerror=function(){var a=b.error;a.code!==a.ABORT_ERR&&E()};["writestart","progress","write","abort"].forEach(function(a){b["on"+a]=h["on"+a]});b.write(k);h.abort=function(){b.abort();h.readyState=h.DONE};h.readyState=h.WRITING}),E)}),E)};a.getFile(m,{create:!1},A(function(a){a.remove();b()}),A(function(a){a.code===a.NOT_FOUND_ERR?b():E()}))}),E)}),E)):E()}},z=k.prototype;if("undefined"!==typeof navigator&&navigator.msSaveOrOpenBlob)return function(a,
928 b,c){c||(a=x(a));return navigator.msSaveOrOpenBlob(a,b||"download")};z.abort=function(){this.readyState=this.DONE;n(this,"abort")};z.readyState=z.INIT=0;z.WRITING=1;z.DONE=2;z.error=z.onwritestart=z.onprogress=z.onwrite=z.onabort=z.onerror=z.onwriteend=null;return function(a,b,c){return new k(a,b,c)}}}("undefined"!==typeof self&&self||"undefined"!==typeof window&&window||this.content);
929 "undefined"!==typeof module&&module.exports?module.exports.saveAs=saveAs:"undefined"!==typeof define&&null!==define&&null!=define.amd&&define([],function(){return saveAs});
930 -var version="0.8.3",urlvars={},amtstack,wsstack=null,AllWsman="AMT_8021xCredentialContext AMT_8021XProfile AMT_ActiveFilterStatistics AMT_AgentPresenceCapabilities AMT_AgentPresenceInterfacePolicy AMT_AgentPresenceService AMT_AgentPresenceWatchdog AMT_AgentPresenceWatchdogAction AMT_AlarmClockService IPS_AlarmClockOccurrence AMT_AssetTable AMT_AssetTableService AMT_AuditLog AMT_AuditPolicyRule AMT_AuthorizationService AMT_BootCapabilities AMT_BootSettingData AMT_ComplexFilterEntryBase AMT_CRL AMT_CryptographicCapabilities AMT_EACCredentialContext AMT_EndpointAccessControlService AMT_EnvironmentDetectionInterfacePolicy AMT_EnvironmentDetectionSettingData AMT_EthernetPortSettings AMT_EventLogEntry AMT_EventManagerService AMT_EventSubscriber AMT_FilterEntryBase AMT_FilterInSystemDefensePolicy AMT_GeneralSettings AMT_GeneralSystemDefenseCapabilities AMT_Hdr8021Filter AMT_HeuristicPacketFilterInterfacePolicy AMT_HeuristicPacketFilterSettings AMT_HeuristicPacketFilterStatistics AMT_InterfacePolicy AMT_IPHeadersFilter AMT_KerberosSettingData AMT_ManagementPresenceRemoteSAP AMT_MessageLog AMT_MPSUsernamePassword AMT_NetworkFilter AMT_NetworkPortDefaultSystemDefensePolicy AMT_NetworkPortSystemDefenseCapabilities AMT_NetworkPortSystemDefensePolicy AMT_PCIDevice AMT_PETCapabilities AMT_PETFilterForTarget AMT_PETFilterSetting AMT_ProvisioningCertificateHash AMT_PublicKeyCertificate AMT_PublicKeyManagementCapabilities AMT_PublicKeyManagementService AMT_PublicPrivateKeyPair AMT_RedirectionService AMT_RemoteAccessCapabilities AMT_RemoteAccessCredentialContext AMT_RemoteAccessPolicyAppliesToMPS AMT_RemoteAccessPolicyRule AMT_RemoteAccessService AMT_SetupAndConfigurationService AMT_SNMPEventSubscriber AMT_StateTransitionCondition AMT_SystemDefensePolicy AMT_SystemDefensePolicyInService AMT_SystemDefenseService AMT_SystemPowerScheme AMT_ThirdPartyDataStorageAdministrationService AMT_ThirdPartyDataStorageService AMT_TimeSynchronizationService AMT_TLSCredentialContext AMT_TLSProtocolEndpoint AMT_TLSProtocolEndpointCollection AMT_TLSSettingData AMT_TrapTargetForService AMT_UserInitiatedConnectionService AMT_WebUIService AMT_WiFiPortConfigurationService CIM_AbstractIndicationSubscription CIM_Account CIM_AccountManagementCapabilities CIM_AccountManagementService CIM_AccountOnSystem CIM_AdminDomain CIM_AlertIndication CIM_AssignedIdentity CIM_AssociatedPowerManagementService CIM_AuthenticationService CIM_AuthorizationService CIM_BIOSElement CIM_BIOSFeature CIM_BIOSFeatureBIOSElements CIM_BootConfigSetting CIM_BootService CIM_BootSettingData CIM_BootSourceSetting CIM_Capabilities CIM_Card CIM_Chassis CIM_Chip CIM_Collection CIM_Component CIM_ComputerSystem CIM_ComputerSystemPackage CIM_ConcreteComponent CIM_ConcreteDependency CIM_Controller CIM_CoolingDevice CIM_Credential CIM_CredentialContext CIM_CredentialManagementService CIM_Dependency CIM_DeviceSAPImplementation CIM_ElementCapabilities CIM_ElementConformsToProfile CIM_ElementLocation CIM_ElementSettingData CIM_ElementSoftwareIdentity CIM_ElementStatisticalData CIM_EnabledLogicalElement CIM_EnabledLogicalElementCapabilities CIM_EthernetPort CIM_Fan CIM_FilterCollection CIM_FilterCollectionSubscription CIM_HostedAccessPoint CIM_HostedDependency CIM_HostedService CIM_Identity CIM_IEEE8021xCapabilities CIM_IEEE8021xSettings CIM_Indication CIM_IndicationService CIM_InstalledSoftwareIdentity CIM_KVMRedirectionSAP CIM_LANEndpoint CIM_ListenerDestination CIM_ListenerDestinationWSManagement CIM_Location CIM_Log CIM_LogEntry CIM_LogicalDevice CIM_LogicalElement CIM_LogicalPort CIM_LogicalPortCapabilities CIM_LogManagesRecord CIM_ManagedCredential CIM_ManagedElement CIM_ManagedSystemElement CIM_MediaAccessDevice CIM_MemberOfCollection CIM_Memory CIM_MessageLog CIM_NetworkPort CIM_NetworkPortCapabilities CIM_NetworkPortConfigurationService CIM_OrderedComponent CIM_OwningCollectionElement CIM_OwningJobElement CIM_PCIController CIM_PhysicalComponent CIM_PhysicalElement CIM_PhysicalElementLocation CIM_PhysicalFrame CIM_PhysicalMemory CIM_PhysicalPackage CIM_Policy CIM_PolicyAction CIM_PolicyCondition CIM_PolicyInSystem CIM_PolicyRule CIM_PolicyRuleInSystem CIM_PolicySet CIM_PolicySetAppliesToElement CIM_PolicySetInSystem CIM_PowerManagementCapabilities CIM_PowerManagementService CIM_PowerSupply CIM_Privilege CIM_PrivilegeManagementCapabilities CIM_PrivilegeManagementService CIM_ProcessIndication CIM_Processor CIM_ProtocolEndpoint CIM_ProvidesServiceToElement CIM_Realizes CIM_RecordForLog CIM_RecordLog CIM_RedirectionService CIM_ReferencedProfile CIM_RegisteredProfile CIM_RemoteAccessAvailableToElement CIM_RemoteIdentity CIM_RemotePort CIM_RemoteServiceAccessPoint CIM_Role CIM_RoleBasedAuthorizationService CIM_RoleBasedManagementCapabilities CIM_RoleLimitedToTarget CIM_SAPAvailableForElement CIM_SecurityService CIM_Sensor CIM_Service CIM_ServiceAccessBySAP CIM_ServiceAccessPoint CIM_ServiceAffectsElement CIM_ServiceAvailableToElement CIM_ServiceSAPDependency CIM_ServiceServiceDependency CIM_SettingData CIM_SharedCredential CIM_SoftwareElement CIM_SoftwareFeature CIM_SoftwareFeatureSoftwareElements CIM_SoftwareIdentity CIM_StatisticalData CIM_StorageExtent CIM_System CIM_SystemBIOS CIM_SystemComponent CIM_SystemDevice CIM_SystemPackaging CIM_UseOfLog CIM_Watchdog CIM_WiFiEndpoint CIM_WiFiEndpointCapabilities CIM_WiFiEndpointSettings CIM_WiFiPort CIM_WiFiPortCapabilities IPS_AdminProvisioningRecord IPS_ClientProvisioningRecord IPS_HostBasedSetupService IPS_HostIPSettings IPS_HTTPProxyService IPS_HTTPProxyAccessPoint IPS_IderSessionUsingPort IPS_IPv6PortSettings IPS_KVMRedirectionSettingData IPS_KvmSessionUsingPort IPS_ManualProvisioningRecord IPS_OptInService IPS_PowerManagementService IPS_ProvisioningAuditRecord IPS_ProvisioningRecordLog IPS_RasSessionUsingPort IPS_ScreenConfigurationService IPS_ScreenSettingData IPS_SecIOService IPS_SessionUsingPort IPS_SolSessionUsingPort IPS_TLSProvisioningRecord IPS_WatchDogAction".split(" "),disconnecturl=
930 +var version="0.8.4",urlvars={},amtstack,wsstack=null,AllWsman="AMT_8021xCredentialContext AMT_8021XProfile AMT_ActiveFilterStatistics AMT_AgentPresenceCapabilities AMT_AgentPresenceInterfacePolicy AMT_AgentPresenceService AMT_AgentPresenceWatchdog AMT_AgentPresenceWatchdogAction AMT_AlarmClockService IPS_AlarmClockOccurrence AMT_AssetTable AMT_AssetTableService AMT_AuditLog AMT_AuditPolicyRule AMT_AuthorizationService AMT_BootCapabilities AMT_BootSettingData AMT_ComplexFilterEntryBase AMT_CRL AMT_CryptographicCapabilities AMT_EACCredentialContext AMT_EndpointAccessControlService AMT_EnvironmentDetectionInterfacePolicy AMT_EnvironmentDetectionSettingData AMT_EthernetPortSettings AMT_EventLogEntry AMT_EventManagerService AMT_EventSubscriber AMT_FilterEntryBase AMT_FilterInSystemDefensePolicy AMT_GeneralSettings AMT_GeneralSystemDefenseCapabilities AMT_Hdr8021Filter AMT_HeuristicPacketFilterInterfacePolicy AMT_HeuristicPacketFilterSettings AMT_HeuristicPacketFilterStatistics AMT_InterfacePolicy AMT_IPHeadersFilter AMT_KerberosSettingData AMT_ManagementPresenceRemoteSAP AMT_MessageLog AMT_MPSUsernamePassword AMT_NetworkFilter AMT_NetworkPortDefaultSystemDefensePolicy AMT_NetworkPortSystemDefenseCapabilities AMT_NetworkPortSystemDefensePolicy AMT_PCIDevice AMT_PETCapabilities AMT_PETFilterForTarget AMT_PETFilterSetting AMT_ProvisioningCertificateHash AMT_PublicKeyCertificate AMT_PublicKeyManagementCapabilities AMT_PublicKeyManagementService AMT_PublicPrivateKeyPair AMT_RedirectionService AMT_RemoteAccessCapabilities AMT_RemoteAccessCredentialContext AMT_RemoteAccessPolicyAppliesToMPS AMT_RemoteAccessPolicyRule AMT_RemoteAccessService AMT_SetupAndConfigurationService AMT_SNMPEventSubscriber AMT_StateTransitionCondition AMT_SystemDefensePolicy AMT_SystemDefensePolicyInService AMT_SystemDefenseService AMT_SystemPowerScheme AMT_ThirdPartyDataStorageAdministrationService AMT_ThirdPartyDataStorageService AMT_TimeSynchronizationService AMT_TLSCredentialContext AMT_TLSProtocolEndpoint AMT_TLSProtocolEndpointCollection AMT_TLSSettingData AMT_TrapTargetForService AMT_UserInitiatedConnectionService AMT_WebUIService AMT_WiFiPortConfigurationService CIM_AbstractIndicationSubscription CIM_Account CIM_AccountManagementCapabilities CIM_AccountManagementService CIM_AccountOnSystem CIM_AdminDomain CIM_AlertIndication CIM_AssignedIdentity CIM_AssociatedPowerManagementService CIM_AuthenticationService CIM_AuthorizationService CIM_BIOSElement CIM_BIOSFeature CIM_BIOSFeatureBIOSElements CIM_BootConfigSetting CIM_BootService CIM_BootSettingData CIM_BootSourceSetting CIM_Capabilities CIM_Card CIM_Chassis CIM_Chip CIM_Collection CIM_Component CIM_ComputerSystem CIM_ComputerSystemPackage CIM_ConcreteComponent CIM_ConcreteDependency CIM_Controller CIM_CoolingDevice CIM_Credential CIM_CredentialContext CIM_CredentialManagementService CIM_Dependency CIM_DeviceSAPImplementation CIM_ElementCapabilities CIM_ElementConformsToProfile CIM_ElementLocation CIM_ElementSettingData CIM_ElementSoftwareIdentity CIM_ElementStatisticalData CIM_EnabledLogicalElement CIM_EnabledLogicalElementCapabilities CIM_EthernetPort CIM_Fan CIM_FilterCollection CIM_FilterCollectionSubscription CIM_HostedAccessPoint CIM_HostedDependency CIM_HostedService CIM_Identity CIM_IEEE8021xCapabilities CIM_IEEE8021xSettings CIM_Indication CIM_IndicationService CIM_InstalledSoftwareIdentity CIM_KVMRedirectionSAP CIM_LANEndpoint CIM_ListenerDestination CIM_ListenerDestinationWSManagement CIM_Location CIM_Log CIM_LogEntry CIM_LogicalDevice CIM_LogicalElement CIM_LogicalPort CIM_LogicalPortCapabilities CIM_LogManagesRecord CIM_ManagedCredential CIM_ManagedElement CIM_ManagedSystemElement CIM_MediaAccessDevice CIM_MemberOfCollection CIM_Memory CIM_MessageLog CIM_NetworkPort CIM_NetworkPortCapabilities CIM_NetworkPortConfigurationService CIM_OrderedComponent CIM_OwningCollectionElement CIM_OwningJobElement CIM_PCIController CIM_PhysicalComponent CIM_PhysicalElement CIM_PhysicalElementLocation CIM_PhysicalFrame CIM_PhysicalMemory CIM_PhysicalPackage CIM_Policy CIM_PolicyAction CIM_PolicyCondition CIM_PolicyInSystem CIM_PolicyRule CIM_PolicyRuleInSystem CIM_PolicySet CIM_PolicySetAppliesToElement CIM_PolicySetInSystem CIM_PowerManagementCapabilities CIM_PowerManagementService CIM_PowerSupply CIM_Privilege CIM_PrivilegeManagementCapabilities CIM_PrivilegeManagementService CIM_ProcessIndication CIM_Processor CIM_ProtocolEndpoint CIM_ProvidesServiceToElement CIM_Realizes CIM_RecordForLog CIM_RecordLog CIM_RedirectionService CIM_ReferencedProfile CIM_RegisteredProfile CIM_RemoteAccessAvailableToElement CIM_RemoteIdentity CIM_RemotePort CIM_RemoteServiceAccessPoint CIM_Role CIM_RoleBasedAuthorizationService CIM_RoleBasedManagementCapabilities CIM_RoleLimitedToTarget CIM_SAPAvailableForElement CIM_SecurityService CIM_Sensor CIM_Service CIM_ServiceAccessBySAP CIM_ServiceAccessPoint CIM_ServiceAffectsElement CIM_ServiceAvailableToElement CIM_ServiceSAPDependency CIM_ServiceServiceDependency CIM_SettingData CIM_SharedCredential CIM_SoftwareElement CIM_SoftwareFeature CIM_SoftwareFeatureSoftwareElements CIM_SoftwareIdentity CIM_StatisticalData CIM_StorageExtent CIM_System CIM_SystemBIOS CIM_SystemComponent CIM_SystemDevice CIM_SystemPackaging CIM_UseOfLog CIM_Watchdog CIM_WiFiEndpoint CIM_WiFiEndpointCapabilities CIM_WiFiEndpointSettings CIM_WiFiPort CIM_WiFiPortCapabilities IPS_AdminProvisioningRecord IPS_ClientProvisioningRecord IPS_HostBasedSetupService IPS_HostIPSettings IPS_HTTPProxyService IPS_HTTPProxyAccessPoint IPS_IderSessionUsingPort IPS_IPv6PortSettings IPS_KVMRedirectionSettingData IPS_KvmSessionUsingPort IPS_ManualProvisioningRecord IPS_OptInService IPS_PowerManagementService IPS_ProvisioningAuditRecord IPS_ProvisioningRecordLog IPS_RasSessionUsingPort IPS_ScreenConfigurationService IPS_ScreenSettingData IPS_SecIOService IPS_SessionUsingPort IPS_SolSessionUsingPort IPS_TLSProvisioningRecord IPS_WatchDogAction".split(" "),disconnecturl=
931 null,terminal,currentView=0,LoadingHtml="<div style=text-align:center;padding-top:20px>Loading...<div>",amtversion=0,amtversionmin=0,amtFirstPull=0,amtwirelessif=-1,desktop,desktopsettings={encoding:1,showfocus:!1,showmouse:!0,showcad:!0,limitFrameRate:!1,noMouseRotate:!1},currentMeshNode=null,webcompilerfeatures="AgentPresence Alarms AuditLog Certificates ComputerSelectorToolbar Desktop DesktopInband DesktopInbandFiles Desktop-Multi DesktopRotation Desktop-Settings DesktopType EventLog EventSubscriptions FileSaver HardwareInfo IDER IDERDebug IDERStats Inflate Look-MeshCentral Mode-MeshCentral2 NetworkSettings PowerControl PowerControl-Advanced RemoteAccess Scripting Scripting-Editor Storage SystemDefense Terminal Terminal-Enumation-All Terminal-FxEnumation-All TerminalSize VersionWarning Wireless WsmanBrowser".split(" "),
932 StatusStrs=["Disconnected","Connecting...","Setup...","Connected"],scriptstate,t,t2,rsepass=null;
933 function startup(){var b=document.getElementsByTagName("input");for(t=0;t<b.length;t++)b[t].id&&(window[b[t].id]=b[t]);urlvars=getUrlVars();for(var c in AllWsman)b=document.createElement("option"),b.text=AllWsman[c],b.id="WSB-"+AllWsman[c],Q(24).add(b);desktop=CreateAmtRedirect(CreateAmtRemoteDesktop("Desk",Q(8)));desktop.onStateChanged=onDesktopStateChange;QE("c10",!0);try{t=localStorage.getItem("desktopsettings")}catch(a){}t&&(desktopsettings=JSON.parse(t));
views/default.handlebars
+76 -1
@@ -234,6 +234,7 @@
234 <input id=SearchInput type=text placeholder=Filter onchange=onDeviceSearchChanged(event) onkeyup=onDeviceSearchChanged(event) autocomplete=off onfocus=onSearchFocus(1) onblur=onSearchFocus(0) />&nbsp;
235 <label><input type=checkbox id=RealNameCheckBox onclick=onRealNameCheckBox() /><span title="Show devices operating system name">OS Name</span></label>
236 <label><input type=checkbox id=OnlineCheckBox onclick=onOnlineCheckBox(event) /><span title="Only show devices that are online">Online</span></label>
237 + <span id="devCustomUIBar"></span>
238 </td>
239 <td id=kvmListToolbar class=style14 style="display:none">
240 &nbsp;&nbsp;<input type="button" onclick="connectAllKvmFunction()" value="Connect All" />&nbsp;
@@ -1230,6 +1231,8 @@
1231 var attemptWebRTC = ((features & 128) != 0);
1232 var passRequirements = '{{{passRequirements}}}';
1233 if (passRequirements != '') { passRequirements = JSON.parse(decodeURIComponent(passRequirements)); }
1234 + var customui = '{{{customui}}}';
1235 + if (customui != '') { customui = JSON.parse(decodeURIComponent(customui)); } else { customui = null; }
1236 var deskAspectRatio = 0;
1237 try { deskAspectRatio = parseInt(getstore('deskAspectRatio', '0')); } catch (ex) { }
1238 var uiMode = parseInt(getstore('uiMode', 1));
@@ -1401,6 +1404,68 @@
1404 if ((['en','ko','ja','zh-chs'].indexOf('{{{lang}}}') == -1) && ('{{{lang}}}'.toLowerCase() != '')) { QC('body').add('nonenglish'); }
1405 var elements = document.getElementsByClassName('topbar_td');
1406 for (var i in elements) { if (elements[i].innerHTML) { elements[i].innerHTML = elements[i].innerHTML.split(' ').join('&nbsp;'); } }
1407 +
1408 + // Custom UI
1409 + if (customui != null) {
1410 + if (customui.devicesbarbuttons) {
1411 + var x = '';
1412 + for (var i in customui.devicesbarbuttons) {
1413 + var disabled = ((customui.devicesbarbuttons[i].selection == 'one') || (customui.devicesbarbuttons[i].selection == 'many'))?'disabled':'';
1414 + x += '<input id="cui:' + i + '" type="button" value="' + customui.devicesbarbuttons[i].name + '" ' + disabled + ' onclick=customUIAction(event,"devicesbarbuttons") />';
1415 + }
1416 + QH('devCustomUIBar', x);
1417 + }
1418 + }
1419 + }
1420 +
1421 + // Generic handling of custom actions
1422 + function customUIAction(e, section) {
1423 + var id = e.srcElement.id;
1424 + if (id.startsWith('cui:') == false) return;
1425 + var info = customui[section][id.substring(4)];
1426 + if (info == null) return;
1427 + if (section == 'devicesbarbuttons') {
1428 + var elements = document.getElementsByClassName('DeviceCheckbox'), selectedDevices = [];
1429 + for (var i = 0; i < elements.length; i++) { if (elements[i].checked === true) { selectedDevices.push(elements[i].defaultValue.substring(6)); } }
1430 + if (typeof info.action == 'string') {
1431 + if (info.action == 'event') { meshserver.send({ action: 'uicustomevent', section: section, element: id.substring(4), selectedDevices: selectedDevices }); }
1432 + if (info.action.startsWith('dialog:')) { showCustomUiDialog(info.action.substring(7), { section: section, element: id.substring(4), selectedDevices: selectedDevices }); }
1433 + }
1434 + }
1435 + }
1436 +
1437 + // Display a generic custom UI dialog
1438 + function showCustomUiDialog(name, tag) {
1439 + if ((customui == null) || (customui.dialogs == null) || (typeof customui.dialogs[name] != 'object')) return;
1440 + var x = '', dialog = customui.dialogs[name], buttons = 3;
1441 + if (typeof dialog.text == 'string') { x += '<div style=margin-bottom:8px>' + dialog.text + '</div>'; }
1442 + if (typeof dialog.buttons == 'number') { buttons = dialog.buttons; }
1443 + if (typeof dialog.elements == 'object') {
1444 + for (var i in dialog.elements) {
1445 + var elem = dialog.elements[i];
1446 + if (elem.type == 'text') { x += addHtmlValue(elem.name, '<input id=cui:' + i + ' style=width:230px autocomplete=off />'); }
1447 + if (elem.type == 'droplist') {
1448 + var y = '';
1449 + for (var j in elem.options) { y += '<option value="' + j + '">' + EscapeHtml(elem.options[j]) + '</option>'; }
1450 + x += addHtmlValue(elem.name, '<select id="cui:' + i + '" style=width:230px autocomplete=off />' + y + '</select>');
1451 + }
1452 + }
1453 + }
1454 + setDialogMode(2, dialog.title, buttons, showCustomUiDialogEx, x, { action: 'uicustomevent', section: 'dialogs', element: name, src: tag, values: {} });
1455 + }
1456 +
1457 + // Handle a generic custom UI dialog event
1458 + function showCustomUiDialogEx(b, t) {
1459 + if (b != 1) return;
1460 + var dialog = customui.dialogs[t.element];
1461 + if (typeof dialog.elements == 'object') {
1462 + for (var i in dialog.elements) {
1463 + var elem = dialog.elements[i];
1464 + if (elem.type == 'text') { t.values[i] = Q('cui:' + i).value; }
1465 + if (elem.type == 'droplist') { t.values[i] = Q('cui:' + i).value; }
1466 + }
1467 + }
1468 + meshserver.send(t);
1469 }
1470
1471 function adjustPanels() {
@@ -4033,6 +4098,16 @@
4098 QV('cxmgroupsplit', false);
4099 QV('cxmdesktop', false);
4100 }
4101 +
4102 + // Custom UI
4103 + if (customui != null) {
4104 + if (customui.devicesbarbuttons) {
4105 + for (var i in customui.devicesbarbuttons) {
4106 + if (customui.devicesbarbuttons[i].selection == 'one') { QE('cui:' + i, checkcount == 1); }
4107 + if (customui.devicesbarbuttons[i].selection == 'many') { QE('cui:' + i, checkcount >= 1); }
4108 + }
4109 + }
4110 + }
4111 }
4112
4113 function groupActionFunction() {
@@ -7316,7 +7391,7 @@
7391 h = '<div class=filelist file=999><input file=999 style=float:left name=fd class=fcb type=checkbox onchange=p13setActions() value=\'' + f.nx + '\'>&nbsp;<span style=float:right title="' + title + '">' + right + '</span><span><div class=fileIcon' + f.t + ' onclick=p13folderset("' + encodeURIComponentEx(f.nx) + '")></div><a href=# style=cursor:pointer onclick=\'return p13folderset("' + encodeURIComponentEx(f.nx) + '")\'>' + shortname + '</a></span></div>';
7392 } else {
7393 var link = shortname;
7319 - if (f.s > 0) { link = '<a href=# rel="noreferrer noopener" target="_blank" style=cursor:pointer onclick="return p13downloadfile(\'' + encodeURIComponentEx(newlinkpath + '/' + name) + '\',\'' + encodeURIComponentEx(name) + '\',' + f.s + ')">' + shortname + '</a>'; }
7394 + if (f.s > 0) { link = '<a href=# rel="noreferrer noopener" target="_blank" download style=cursor:pointer onclick="return p13downloadfile(\'' + encodeURIComponentEx(newlinkpath + '/' + name) + '\',\'' + encodeURIComponentEx(name) + '\',' + f.s + ')">' + shortname + '</a>'; }
7395 h = '<div id=fileEntry cmenu=filesContextMenu fileIndex=' + i + ' class=filelist file=3><input file=3 style=float:left name=fd class=fcb type=checkbox onchange=p13setActions() value=\'' + f.nx + '\'>&nbsp;<span class=fsize>' + fdatestr + '</span><span style=float:right>' + fsize + '</span><span><div class=fileIcon' + f.t + '></div>' + link + '</span></div>';
7396 }
7397
webserver.js
+11 -2
@@ -2180,7 +2180,12 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
2180 for (var i in domain.forceduserwebstate) { webstate2[i] = domain.forceduserwebstate[i]; }
2181 webstate = JSON.stringify(webstate2);
2182 }
2183 - render(req, res, getRenderPage('default', req, domain), getRenderArgs({ authCookie: authCookie, authRelayCookie: authRelayCookie, viewmode: viewmode, currentNode: currentNode, logoutControls: encodeURIComponent(JSON.stringify(logoutcontrols)).replace(/'/g, '%27'), domain: domain.id, debuglevel: parent.debugLevel, serverDnsName: obj.getWebServerName(domain), serverRedirPort: args.redirport, serverPublicPort: httpsPort, noServerBackup: (args.noserverbackup == 1 ? 1 : 0), features: features, sessiontime: args.sessiontime, mpspass: args.mpspass, passRequirements: passRequirements, webcerthash: Buffer.from(obj.webCertificateFullHashs[domain.id], 'binary').toString('base64').replace(/\+/g, '@').replace(/\//g, '$'), footer: (domain.footer == null) ? '' : domain.footer, webstate: encodeURIComponent(webstate), pluginHandler: (parent.pluginHandler == null) ? 'null' : parent.pluginHandler.prepExports() }, req, domain));
2183 +
2184 + // Custom user interface
2185 + var customui = '';
2186 + if (domain.customui != null) { customui = encodeURIComponent(JSON.stringify(domain.customui)); }
2187 +
2188 + render(req, res, getRenderPage('default', req, domain), getRenderArgs({ authCookie: authCookie, authRelayCookie: authRelayCookie, viewmode: viewmode, currentNode: currentNode, logoutControls: encodeURIComponent(JSON.stringify(logoutcontrols)).replace(/'/g, '%27'), domain: domain.id, debuglevel: parent.debugLevel, serverDnsName: obj.getWebServerName(domain), serverRedirPort: args.redirport, serverPublicPort: httpsPort, noServerBackup: (args.noserverbackup == 1 ? 1 : 0), features: features, sessiontime: args.sessiontime, mpspass: args.mpspass, passRequirements: passRequirements, customui: customui, webcerthash: Buffer.from(obj.webCertificateFullHashs[domain.id], 'binary').toString('base64').replace(/\+/g, '@').replace(/\//g, '$'), footer: (domain.footer == null) ? '' : domain.footer, webstate: encodeURIComponent(webstate), pluginHandler: (parent.pluginHandler == null) ? 'null' : parent.pluginHandler.prepExports() }, req, domain));
2189 });
2190 } else {
2191 // Send back the login application
@@ -2269,8 +2274,12 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
2274 if (typeof domain.authstrategies.saml == 'object') { authStrategies.push('saml'); }
2275 }
2276
2277 + // Custom user interface
2278 + var customui = '';
2279 + if (domain.customui != null) { customui = encodeURIComponent(JSON.stringify(domain.customui)); }
2280 +
2281 // Render the login page
2273 - render(req, res, getRenderPage('login', req, domain), getRenderArgs({ loginmode: loginmode, rootCertLink: getRootCertLink(), newAccount: newAccountsAllowed, newAccountPass: (((domain.newaccountspass == null) || (domain.newaccountspass == '')) ? 0 : 1), serverDnsName: obj.getWebServerName(domain), serverPublicPort: httpsPort, emailcheck: emailcheck, features: features, sessiontime: args.sessiontime, passRequirements: passRequirements, footer: (domain.footer == null) ? '' : domain.footer, hkey: encodeURIComponent(hardwareKeyChallenge), messageid: msgid, passhint: passhint, welcometext: domain.welcometext ? encodeURIComponent(domain.welcometext).split('\'').join('\\\'') : null, hwstate: hwstate, otpemail: otpemail, otpsms: otpsms, twoFactorCookieDays: twoFactorCookieDays, authStrategies: authStrategies.join(',') }, req, domain));
2282 + render(req, res, getRenderPage('login', req, domain), getRenderArgs({ loginmode: loginmode, rootCertLink: getRootCertLink(), newAccount: newAccountsAllowed, newAccountPass: (((domain.newaccountspass == null) || (domain.newaccountspass == '')) ? 0 : 1), serverDnsName: obj.getWebServerName(domain), serverPublicPort: httpsPort, emailcheck: emailcheck, features: features, sessiontime: args.sessiontime, passRequirements: passRequirements, customui: customui, footer: (domain.footer == null) ? '' : domain.footer, hkey: encodeURIComponent(hardwareKeyChallenge), messageid: msgid, passhint: passhint, welcometext: domain.welcometext ? encodeURIComponent(domain.welcometext).split('\'').join('\\\'') : null, hwstate: hwstate, otpemail: otpemail, otpsms: otpsms, twoFactorCookieDays: twoFactorCookieDays, authStrategies: authStrategies.join(',') }, req, domain));
2283 }
2284
2285 // Handle a post request on the root