mirror of
				https://github.com/Ylianst/MeshCentral.git
				synced 2025-10-29 15:25:01 -04:00 
			
		
		
		
	Added support for custom ui buttons and dialogs.
This commit is contained in:
		
							parent
							
								
									04188019a0
								
							
						
					
					
						commit
						8c0ae5bb52
					
				| @ -61,9 +61,7 @@ | ||||
|     <Compile Include="agents\modules_meshcore\amt-xml.js" /> | ||||
|     <Compile Include="agents\modules_meshcore\amt.js" /> | ||||
|     <Compile Include="agents\modules_meshcore\apfclient.js" /> | ||||
|     <Compile Include="agents\modules_meshcore\identifiers.js" /> | ||||
|     <Compile Include="agents\modules_meshcore\monitor-border.js" /> | ||||
|     <Compile Include="agents\modules_meshcore\power-monitor.js" /> | ||||
|     <Compile Include="agents\modules_meshcore\smbios.js" /> | ||||
|     <Compile Include="agents\modules_meshcore\sysinfo.js" /> | ||||
|     <Compile Include="agents\modules_meshcore\wifi-scanner-windows.js" /> | ||||
|  | ||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							| @ -27,7 +27,6 @@ function amt_heci() { | ||||
|     this._setupPTHI = function _setupPTHI() | ||||
|     { | ||||
|         this._amt = heci.create(); | ||||
|         this._amt.descriptorMetadata = "amt-pthi"; | ||||
|         this._amt.BiosVersionLen = 65; | ||||
|         this._amt.UnicodeStringLen = 20; | ||||
| 
 | ||||
| @ -398,25 +397,20 @@ function amt_heci() { | ||||
|             fn.apply(this, opt); | ||||
|         }, callback, optional); | ||||
|     } | ||||
|     this.getProtocolVersion = function getProtocolVersion(callback) | ||||
|     { | ||||
|     this.getProtocolVersion = function getProtocolVersion(callback) { | ||||
|         var optional = []; | ||||
|         for (var i = 1; i < arguments.length; ++i) { opt.push(arguments[i]); } | ||||
| 
 | ||||
|         if (!this._tmpSession) { this._tmpSession = heci.create(); this._tmpSession.parent = this;} | ||||
|         this._tmpSession.doIoctl(heci.IOCTL.HECI_VERSION, Buffer.alloc(5), Buffer.alloc(5), function (status, buffer, self, fn, opt) | ||||
|         { | ||||
|         heci.doIoctl(heci.IOCTL.HECI_VERSION, Buffer.alloc(5), Buffer.alloc(5), function (status, buffer, self, fn, opt) { | ||||
|             if (status == 0) { | ||||
|                 var result = buffer.readUInt8(0).toString() + '.' + buffer.readUInt8(1).toString() + '.' + buffer.readUInt8(2).toString() + '.' + buffer.readUInt16BE(3).toString(); | ||||
|                 opt.unshift(result); | ||||
|                 fn.apply(self, opt); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|             else { | ||||
|                 opt.unshift(null); | ||||
|                 fn.apply(self, opt); | ||||
|             } | ||||
| 
 | ||||
|         }, this, callback, optional); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -4323,6 +4323,15 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use | ||||
|                 } | ||||
|                 break; | ||||
|             } | ||||
|             case 'uicustomevent': { | ||||
|                 // Event the change
 | ||||
|                 var message = { etype: 'user', userid: user._id, username: user.name, action: 'uicustomevent', domain: domain.id, nolog: 1, uisection: command.section, element: command.element  }; | ||||
|                 if (command.selectedDevices != null) { message.selectedDevices = command.selectedDevices; } | ||||
|                 if (command.src != null) { message.src = command.src; } | ||||
|                 if (command.values != null) { message.values = command.values; } | ||||
|                 parent.parent.DispatchEvent(['*', user._id], obj, message); | ||||
|                 break; | ||||
|             } | ||||
|             default: { | ||||
|                 // Unknown user action
 | ||||
|                 console.log('Unknown action from user ' + user.name + ': ' + command.action + '.'); | ||||
|  | ||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @ -234,6 +234,7 @@ | ||||
|                             <input id=SearchInput type=text placeholder=Filter onchange=onDeviceSearchChanged(event) onkeyup=onDeviceSearchChanged(event) autocomplete=off onfocus=onSearchFocus(1) onblur=onSearchFocus(0) />  | ||||
|                             <label><input type=checkbox id=RealNameCheckBox onclick=onRealNameCheckBox() /><span title="Show devices operating system name">OS Name</span></label> | ||||
|                             <label><input type=checkbox id=OnlineCheckBox onclick=onOnlineCheckBox(event) /><span title="Only show devices that are online">Online</span></label> | ||||
|                             <span id="devCustomUIBar"></span> | ||||
|                         </td> | ||||
|                         <td id=kvmListToolbar class=style14 style="display:none"> | ||||
|                               <input type="button" onclick="connectAllKvmFunction()" value="Connect All" />  | ||||
| @ -1230,6 +1231,8 @@ | ||||
|         var attemptWebRTC = ((features & 128) != 0); | ||||
|         var passRequirements = '{{{passRequirements}}}'; | ||||
|         if (passRequirements != '') { passRequirements = JSON.parse(decodeURIComponent(passRequirements)); } | ||||
|         var customui = '{{{customui}}}'; | ||||
|         if (customui != '') { customui = JSON.parse(decodeURIComponent(customui)); } else { customui = null; } | ||||
|         var deskAspectRatio = 0; | ||||
|         try { deskAspectRatio = parseInt(getstore('deskAspectRatio', '0')); } catch (ex) { } | ||||
|         var uiMode = parseInt(getstore('uiMode', 1)); | ||||
| @ -1401,6 +1404,68 @@ | ||||
|             if ((['en','ko','ja','zh-chs'].indexOf('{{{lang}}}') == -1) && ('{{{lang}}}'.toLowerCase() != '')) { QC('body').add('nonenglish'); } | ||||
|             var elements = document.getElementsByClassName('topbar_td'); | ||||
|             for (var i in elements) { if (elements[i].innerHTML) { elements[i].innerHTML = elements[i].innerHTML.split(' ').join(' '); } } | ||||
| 
 | ||||
|             // Custom UI | ||||
|             if (customui != null) { | ||||
|                 if (customui.devicesbarbuttons) { | ||||
|                     var x = ''; | ||||
|                     for (var i in customui.devicesbarbuttons) { | ||||
|                         var disabled = ((customui.devicesbarbuttons[i].selection == 'one') || (customui.devicesbarbuttons[i].selection == 'many'))?'disabled':''; | ||||
|                         x += '<input id="cui:' + i + '" type="button" value="' + customui.devicesbarbuttons[i].name + '" ' + disabled + ' onclick=customUIAction(event,"devicesbarbuttons") />'; | ||||
|                     } | ||||
|                     QH('devCustomUIBar', x); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // Generic handling of custom actions | ||||
|         function customUIAction(e, section) { | ||||
|             var id = e.srcElement.id; | ||||
|             if (id.startsWith('cui:') == false) return; | ||||
|             var info = customui[section][id.substring(4)]; | ||||
|             if (info == null) return; | ||||
|             if (section == 'devicesbarbuttons') { | ||||
|                 var elements = document.getElementsByClassName('DeviceCheckbox'), selectedDevices = []; | ||||
|                 for (var i = 0; i < elements.length; i++) { if (elements[i].checked === true) { selectedDevices.push(elements[i].defaultValue.substring(6)); } } | ||||
|                 if (typeof info.action == 'string') { | ||||
|                     if (info.action == 'event') { meshserver.send({ action: 'uicustomevent', section: section, element: id.substring(4), selectedDevices: selectedDevices }); } | ||||
|                     if (info.action.startsWith('dialog:')) { showCustomUiDialog(info.action.substring(7), { section: section, element: id.substring(4), selectedDevices: selectedDevices }); } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // Display a generic custom UI dialog | ||||
|         function showCustomUiDialog(name, tag) { | ||||
|             if ((customui == null) || (customui.dialogs == null) || (typeof customui.dialogs[name] != 'object')) return; | ||||
|             var x = '', dialog = customui.dialogs[name], buttons = 3; | ||||
|             if (typeof dialog.text == 'string') { x += '<div style=margin-bottom:8px>' + dialog.text + '</div>'; } | ||||
|             if (typeof dialog.buttons == 'number') { buttons = dialog.buttons; } | ||||
|             if (typeof dialog.elements == 'object') {  | ||||
|                 for (var i in dialog.elements) { | ||||
|                     var elem = dialog.elements[i]; | ||||
|                     if (elem.type == 'text') { x += addHtmlValue(elem.name, '<input id=cui:' + i + ' style=width:230px autocomplete=off />'); } | ||||
|                     if (elem.type == 'droplist') { | ||||
|                         var y = ''; | ||||
|                         for (var j in elem.options) { y += '<option value="' + j + '">' + EscapeHtml(elem.options[j]) + '</option>'; } | ||||
|                         x += addHtmlValue(elem.name, '<select id="cui:' + i + '" style=width:230px autocomplete=off />' + y + '</select>'); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             setDialogMode(2, dialog.title, buttons, showCustomUiDialogEx, x, { action: 'uicustomevent', section: 'dialogs', element: name, src: tag, values: {} }); | ||||
|         } | ||||
| 
 | ||||
|         // Handle a generic custom UI dialog event | ||||
|         function showCustomUiDialogEx(b, t) { | ||||
|             if (b != 1) return; | ||||
|             var dialog = customui.dialogs[t.element]; | ||||
|             if (typeof dialog.elements == 'object') {  | ||||
|                 for (var i in dialog.elements) { | ||||
|                     var elem = dialog.elements[i]; | ||||
|                     if (elem.type == 'text') { t.values[i] = Q('cui:' + i).value; } | ||||
|                     if (elem.type == 'droplist') { t.values[i] = Q('cui:' + i).value; } | ||||
|                 } | ||||
|             } | ||||
|             meshserver.send(t); | ||||
|         } | ||||
| 
 | ||||
|         function adjustPanels() { | ||||
| @ -4033,6 +4098,16 @@ | ||||
|                 QV('cxmgroupsplit', false); | ||||
|                 QV('cxmdesktop', false); | ||||
|             } | ||||
| 
 | ||||
|             // Custom UI | ||||
|             if (customui != null) { | ||||
|                 if (customui.devicesbarbuttons) { | ||||
|                     for (var i in customui.devicesbarbuttons) { | ||||
|                         if (customui.devicesbarbuttons[i].selection == 'one') { QE('cui:' + i, checkcount == 1); } | ||||
|                         if (customui.devicesbarbuttons[i].selection == 'many') { QE('cui:' + i, checkcount >= 1); } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         function groupActionFunction() { | ||||
| @ -7316,7 +7391,7 @@ | ||||
|                     h = '<div class=filelist file=999><input file=999 style=float:left name=fd class=fcb type=checkbox onchange=p13setActions() value=\'' + f.nx + '\'> <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>'; | ||||
|                 } else { | ||||
|                     var link = shortname; | ||||
|                     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>'; } | ||||
|                     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>'; } | ||||
|                     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 + '\'> <span class=fsize>' + fdatestr + '</span><span style=float:right>' + fsize + '</span><span><div class=fileIcon' + f.t + '></div>' + link + '</span></div>'; | ||||
|                 } | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										13
									
								
								webserver.js
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								webserver.js
									
									
									
									
									
								
							| @ -2180,7 +2180,12 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { | ||||
|                     for (var i in domain.forceduserwebstate) { webstate2[i] = domain.forceduserwebstate[i]; } | ||||
|                     webstate = JSON.stringify(webstate2); | ||||
|                 } | ||||
|                 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)); | ||||
| 
 | ||||
|                 // Custom user interface
 | ||||
|                 var customui = ''; | ||||
|                 if (domain.customui != null) { customui = encodeURIComponent(JSON.stringify(domain.customui)); } | ||||
| 
 | ||||
|                 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)); | ||||
|             }); | ||||
|         } else { | ||||
|             // Send back the login application
 | ||||
| @ -2269,8 +2274,12 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { | ||||
|             if (typeof domain.authstrategies.saml == 'object') { authStrategies.push('saml'); } | ||||
|         } | ||||
| 
 | ||||
|         // Custom user interface
 | ||||
|         var customui = ''; | ||||
|         if (domain.customui != null) { customui = encodeURIComponent(JSON.stringify(domain.customui)); } | ||||
| 
 | ||||
|         // Render the login page
 | ||||
|         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)); | ||||
|         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)); | ||||
|     } | ||||
| 
 | ||||
|     // Handle a post request on the root
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user