301 status code means that the requested resource has been permanently moved to a new URL. All future requests should use the new address.
The browser will automatically redirect the user to the new address, and search engines will update their indexes.
200 status code is a standard successful HTTP server response. It means that the client’s request (e.g., from a browser) was successfully processed, and the server is delivering the requested data.
The user receives content without errors, and the page or application functions properly. If Code 200 is accompanied by data, the browser or program processes and displays it to the user.
GET / HTTP/1.1 Host: mmtdr.com Accept: */* User-Agent: Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; [email protected])
<!DOCTYPE html> <html> <head><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" /> <script> function setTaggedSessionInfo(tag, taggedSessionInfo) { var oldTaggedSessionInfo = window._taggedSessionInfos[tag]; window._taggedSessionInfos[tag] = taggedSessionInfo; if (!oldTaggedSessionInfo || taggedSessionInfo.SessionID != oldTaggedSessionInfo.SessionID || taggedSessionInfo.Code != oldTaggedSessionInfo.Code) SC.livedata.notifyDirty(); } // backwards compatibility with extensions function setTaggedSessionID(tag, sessionID) { window.setTaggedSessionInfo(tag, { SessionID: sessionID }); } function getTaggedSessionInfo(tag) { return window._taggedSessionInfos[tag]; } function getSessionInfo() { var liveData = SC.livedata.get(); return liveData && liveData.ResponseInfoMap && liveData.ResponseInfoMap['GuestSessionInfo'] } </script> <script src="Script.ashx?__Cache=20cdfe3b-1132-46e2-ac37-5b2073723429" id="defaultScript"></script> <script src="Scripts/SC.polyfill.ts?ScriptImportType=NoModule&__Cache=96f238ce-2cea-4a1b-b0aa-a26e897eaabe" nomodule="nomodule"></script> <script src="Scripts/SC.main.ts?ScriptImportType=NoModule&__Cache=ec608bce-6a1a-4ea9-ad9d-6b20f636e687" nomodule="nomodule"></script> <script src="Scripts/SC.main.ts?ScriptImportType=Classic&__Cache=ec608bce-6a1a-4ea9-ad9d-6b20f636e687"></script> <link href="App_Themes/SolidWithBlue/Default.css?__Cache=9ee2fbc3-96c0-4abc-b2e3-aa188cc7db17" type="text/css" rel="stylesheet" /><link href="FavIcon.axd?__Cache=7fd8b58e-1634-4d13-8e1c-904d21f2d481" rel="shortcut icon" /> <script>SC.util.mergeIntoContext({"focusedControlID":null,"userName":"","userDisplayName":"","isUserAuthenticated":false,"antiForgeryToken":"3EuJ6QL+r4og3js+gvAaXpSgTAxbzNazoXh7MlELK5wBAAAsSCLCSL8tQg==","isUserAdministrator":false,"canManageSharedToolbox":false,"pageBaseFileName":"Guest","notifyActivityFrequencyMilliseconds":600000,"loginAfterInactivityMilliseconds":36000000,"canChangePassword":false,"controlPanelUrl":null,"pageType":"GuestPage","processType":2,"userAgentOverride":null,"sessionTypeInfos":[],"imports":{"SC.editor":"Scripts/SC.editor.ts?ScriptImportType=EsModule\u0026__Cache=0b989e82-6b9d-4fd8-928e-25735b4d8ebc"}});</script> <link href="App_Extensions/c06711f7-e4a9-40dc-85ea-0f9bdee533b7/Style.css" type="text/css" rel="stylesheet" /> <script src="https://cloud.screenconnect.com/scripts/instance.js?Instance=rfpxmo" async="async" defer="defer"></script> <script>SC.extension.addInitializeProc('3002e42b-3a99-405f-afc2-df854d2496f6', function (extensionContext) { if (shouldOverwriteResourceValues()) { var excludedKeys = new Set(); excludedKeys.add("Command.ToggleOverwriteResourceValues.Text"); excludedKeys.add("ExtensionsPanel.BaseUrl"); var excludedValues = new Set(); excludedValues.add(""); excludedValues.add("false"); excludedValues.add("true"); Object.keys(SC.res) .filter(function (key) { return !excludedValues.has(SC.res[key]) && !excludedKeys.has(key); }) .forEach(function (key) { SC.res[key] = key; }); } function shouldOverwriteResourceValues() { return localStorage.getItem("appearanceEditor:overwriteResourceValues") !== null; } function setOverwriteResourceValues(shouldSetOrUnset) { if (shouldSetOrUnset) localStorage.setItem("appearanceEditor:overwriteResourceValues", "true"); else localStorage.removeItem("appearanceEditor:overwriteResourceValues"); } var hostedWindowUrlSuffix = "#appearance-edit-mode"; SC.event.addGlobalHandler(SC.event.QueryCommandButtons, function (eventArgs) { switch (eventArgs.area) { case "ExtrasPopoutPanel": if (SC.context.isUserAdministrator || shouldOverwriteResourceValues()) eventArgs.buttonDefinitions.push({ commandName: "ToggleOverwriteResourceValues" }); break; } }); SC.event.addGlobalHandler(SC.event.PageDataRefreshed, function () { setTimeout(function () { if (SC.context.tabKeys && SC.context.tabKeys[SC.context.tabIndex] === "Appearance") { $(".AppearanceList").firstChild.appendChild( $p( { className: "CommandList" }, SC.command.createCommandButtons([{ commandName: "SwitchEditor", commandArgument: "Visual" }]) ) ); } }, 0); }); SC.event.addGlobalHandler(SC.event.PreRender, function () { if (SC.context.tabKeys && SC.context.tabKeys[SC.context.tabIndex] === "Appearance") { SC.util.includeStyleSheet(extensionContext.baseUrl + "AppearanceStyles.css"); $("Main_contentPanel").appendChild( $dl({ className: "AppearanceEditor", style: "display: none;" }, [ $dt([ $h3("Appearance Editor"), $p( { className: "CommandList" }, SC.command.createCommandButtons([ // { commandName: 'SwitchPage', commandArgument: 'Guest' }, // { commandName: 'SwitchPage', commandArgument: 'Host' }, // TODO add host page pencils { commandName: "SwitchEditor", commandArgument: "Advanced" }, ]) ), ]), $dd([ $p({ _textResource: "Information.Text" }), $iframe({ src: SC.context.scriptBaseUrl + hostedWindowUrlSuffix, width: "100%", height: "100%" }), ]), ]) ); } else if ( SC.context.pageType === "GuestPage" && window.self !== window.top && location.href.endsWith(hostedWindowUrlSuffix) ) { // in iframe SC.util.includeStyleSheet(extensionContext.baseUrl + "GuestStyles.css"); SC.css.removeClass($("html"), "UserAuthenticated"); function addPencil(element, resourceName) { if (element) element.appendChild( SC.command.createCommandButtons([ { className: "pencil", commandName: "EditAppearanceResource", commandArgument: resourceName, title: resourceName, imageUrl: extensionContext.baseUrl + "/pencil.png", }, ])[0] ); } addPencil($(".LogoPanel"), "LogoPanel.ImageLight"); addPencil($(".LogoIconLink"), "LogoPanel.IconLight"); addPencil($(".WelcomePanel > h2"), "GuestWelcomePanel.Heading"); addPencil($(".WelcomePanel > p"), "GuestWelcomePanel.Message"); addPencil($(".ContentPanel"), "Page.Background"); $$(".ActionPanel > div").forEach(function (element, i) { switch (i) { case 1: addPencil(element, "GuestActionPanel.InvitationSession.Heading"); break; case 2: addPencil(element, "GuestActionPanel.CodeSession.Heading"); break; case 3: addPencil(element, "GuestActionPanel.PublicSession.Heading"); break; case 4: addPencil(element, "GuestActionPanel.NoAvailableSessions.Heading"); break; default: } }); } }); SC.event.addGlobalHandler(SC.event.ExecuteCommand, function (eventArgs) { switch (eventArgs.commandName) { case "SwitchEditor": if (eventArgs.commandArgument === "Visual") { $(".AppearanceList").style.display = "none"; $(".AppearanceEditor").removeAttribute("style"); } else if (eventArgs.commandArgument === "Advanced") { $(".AppearanceList").removeAttribute("style"); $(".AppearanceEditor").style.display = "none"; } break; case "SwitchPage": if (eventArgs.commandArgument === "Guest") { $("iframe").contentWindow.location.href = SC.context.scriptBaseUrl + hostedWindowUrlSuffix; } else if (eventArgs.commandArgument === "Host") { $("iframe").contentWindow.location.href = SC.context.scriptBaseUrl + "/Host" + hostedWindowUrlSuffix; } break; case "EditAppearanceResource": var appearanceListRow = Array.from( window.top.document.querySelectorAll(".AppearanceList .DataTable tbody tr") ).find(function (element) { return element.children[1].textContent === eventArgs.commandArgument; }); var element = appearanceListRow.querySelector(".ActionCell a"); var clickedElement = appearanceListRow.querySelector(".ActionCell a span"); SC.command.dispatchExecuteCommand(element, clickedElement, element, "EditResource"); break; case "ToggleOverwriteResourceValues": setOverwriteResourceValues(!shouldOverwriteResourceValues()); window.location.reload(); break; case "Default": setTimeout(function () { $("iframe").contentWindow.location.reload(); }, 300); break; } }); });</script> <script>SC.extension.addInitializeProc('c06711f7-e4a9-40dc-85ea-0f9bdee533b7', function (extensionContext) { SC.event.addGlobalHandler(SC.event.QueryPanels, function (eventArgs) { switch(eventArgs.area){ case 'GuestActionPanel': if(extensionContext.settingValues.Bottom != "false"){ eventArgs.panelDefinitions.push({ initProc: function (container) { var buildtitle = []; if(extensionContext.settingValues.Title.split(" ").length > 1){ buildtitle = [extensionContext.settingValues.Title.substring(0, extensionContext.settingValues.Title.indexOf(" ")), extensionContext.settingValues.Title.substring(extensionContext.settingValues.Title.indexOf(" "))]; }else{ buildtitle = [extensionContext.settingValues.Title, ""]; } SC.ui.setContents(container, [$h2({ innerHTML: '<em>'+buildtitle[0]+'</em> '+buildtitle[1] }), $table({id: 'installerTable'})]); SC.ui.clear($('installerTable')); SC.ui.addElement($('installerTable'), 'tr', {id: 'BuildInstallerRow'}); SC.ui.addElement($('BuildInstallerRow'), 'td', {id: 'BuildInstallerCell0'}); SC.ui.addElement($('BuildInstallerRow'), 'td', {id: 'BuildInstallerCell1'}); SC.ui.addElement($('BuildInstallerCell0'), 'span', {innerHTML: extensionContext.settingValues.Description}); SC.ui.addElement($('BuildInstallerCell1'), 'a', {id: 'BuildInstallerButton', className: 'GoLink Medium', _commandName: 'ShowBuildInstallerDialog'}); }, isVisibleProc: function (pass, previousPassVisibleCount, sessionInfo) { return pass == 10; } }); }else{ eventArgs.panelDefinitions.unshift({ initProc: function (container) { var buildtitle = []; if(extensionContext.settingValues.Title.split(" ").length > 1){ buildtitle = [extensionContext.settingValues.Title.substring(0, extensionContext.settingValues.Title.indexOf(" ")), extensionContext.settingValues.Title.substring(extensionContext.settingValues.Title.indexOf(" "))]; }else{ buildtitle = [extensionContext.settingValues.Title, ""]; } SC.ui.setContents(container, [$h2({ innerHTML: '<em>'+buildtitle[0]+'</em> '+buildtitle[1] }), $table({id: 'installerTable'})]); SC.ui.clear($('installerTable')); SC.ui.addElement($('installerTable'), 'tr', {id: 'BuildInstallerRow'}); SC.ui.addElement($('BuildInstallerRow'), 'td', {id: 'BuildInstallerCell0'}); SC.ui.addElement($('BuildInstallerRow'), 'td', {id: 'BuildInstallerCell1'}); SC.ui.addElement($('BuildInstallerCell0'), 'span', {innerHTML: extensionContext.settingValues.Description}); SC.ui.addElement($('BuildInstallerCell1'), 'a', {id: 'BuildInstallerButton', className: 'GoLink Medium', _commandName: 'ShowBuildInstallerDialog'}); }, isVisibleProc: function (pass, previousPassVisibleCount, sessionInfo) { return pass == 10; } }); } break; } }); SC.event.addGlobalHandler(SC.event.ExecuteCommand, function (eventArgs) { switch (eventArgs.commandName) { case 'ShowBuildInstallerDialog': if(extensionContext.settingValues.UsePassword != "false"){ var titlePanel = SC.dialog.createTitlePanel("Installer Password"); var mainContentPanel = SC.dialog.createContentPanel(); var buttonPanel = SC.dialog.createButtonPanel("Submit"); var contentContainer = SC.ui.addElement(mainContentPanel, 'span', "Please enter the password: "); SC.ui.addElement(contentContainer, 'input', {name: 'password', type: 'password', _commandName: 'Default', _sessionPropertyName: 'password'}); SC.dialog.showModalDialogRaw('PasswordDialog', [titlePanel, mainContentPanel, buttonPanel], function (eventArgs){ var password = SC.editfield.getElement(contentContainer, 'password'); password = password.value.trim(); if(password == extensionContext.settingValues.Password){ SC.installer.showBuildDialog(); }else{ SC.dialog.setButtonPanelError(buttonPanel, { message: "Password Incorrect." }); return; } }); }else{ SC.installer.showBuildDialog(); } break; } }); });</script> <script>SC.extension.addInitializeProc('158cfe2a-e19f-407a-a9b2-899be383abe7', function (extensionContext) { SC.event.QueryTutorialLinks = 'querytutoriallinks'; SC.event.QueryUsefulLinks = 'queryusefullinks'; SC.event.QueryNeedSupportLinks = 'queryneedsupportlinks'; SC.event.QueryAdditionalSupportLinks = 'queryadditionalsupportlinks'; SC.event.addGlobalHandler(SC.event.QueryCommandButtons, function (eventArgs) { if (SC.context.pageType == 'HostPage' || SC.context.pageType == 'AdministrationPage') { switch (eventArgs.area) { case 'HelpPopoutPanel': eventArgs.buttonDefinitions.push({ commandName: 'ShowEnhancedHelp', text: SC.res['EnhancedHelp.ModalTitle.Text'], }); break; case 'TrayPanel': eventArgs.buttonDefinitions.push({ commandName: 'ShowEnhancedHelp', imageUrl: extensionContext.baseUrl + 'Icons/HelpIconDark.svg', className: 'EnhancedHelpButtonGlobalBar', title: SC.res['EnhancedHelp.ModalTitle.Text'], }); break; case 'TrayIconPanel': eventArgs.buttonDefinitions.push({ commandName: 'ShowEnhancedHelp', imageUrl: extensionContext.baseUrl + 'Icons/HelpIcon.svg', className: 'EnhancedHelpButtonGlobalBar', title: SC.res['EnhancedHelp.ModalTitle.Text'], tooltipOrTitle: true, // tooltipOrTitle is no longer need after live-data branch got merged in, keep this here for backward compatibility }); break; } } }); function createNewWindowLink(resourceKeyWord) { return $a({ _textResource: 'EnhancedHelp.' + resourceKeyWord + '.Text', href: SC.res['EnhancedHelp.' + resourceKeyWord + '.Url'], target: '_blank', className: resourceKeyWord }); } SC.event.addGlobalHandler(SC.event.ExecuteCommand, function (eventArgs) { switch (eventArgs.commandName) { case 'ShowEnhancedHelp': if (SC.context.productVersion.split('.')[0] <= 19 && SC.context.productVersion.split('.')[1] <= 5) { // Added a new way to create modal in 19.6 SC.dialog.showModalDialogRaw('EnhancedHelp', [ SC.dialog.createTitlePanel(SC.res['EnhancedHelp.ModalTitle.Text']), SC.dialog.createContentPanel([ $div({ className: 'GuidesPanel' }, [ createNewWindowLink('ReleaseNotes'), createNewWindowLink('SecurityGuide'), createNewWindowLink('SupportGuide'), createNewWindowLink('AccessGuide'), ]), $div({ className: 'HelpPanel' }, [ $h4({ _textResource: 'EnhancedHelp.IdeasPanel.Title' }), SC.command.createCommandButtons([ { commandName: 'GiveFeedback' }, ]), createNewWindowLink('EnhancementRequest'), ]), $div({ className: 'HelpPanel' }, [ $h4({ _textResource: 'EnhancedHelp.NeedSupportPanel.Title' }), createNewWindowLink('SubmitTicket'), createNewWindowLink('StartChat'), ]), $div({ className: 'MoreHelpPanel' }, [ createNewWindowLink('OnlineHelp'), createNewWindowLink('UserForum'), ]), ]), ]); } else { var retrievedTutorialsInfo = SC.event.dispatchGlobalEvent(SC.event.QueryTutorialLinks, { tutorialLinks: [] }); var retrievedUsefulLinksInfo = SC.event.dispatchGlobalEvent(SC.event.QueryUsefulLinks, { usefulLinks: [] }); var retrievedNeedSupportsInfo = SC.event.dispatchGlobalEvent(SC.event.QueryNeedSupportLinks, { needSupportLinks: [] }); var retrievedAdditionalSupportLinksInfo = SC.event.dispatchGlobalEvent(SC.event.QueryAdditionalSupportLinks, { additionalLinks: [] }); //So that onprem instances don't lose original links since there's now dynamically generated cloud stuff if (SC.util.isNullOrEmpty(SC.context.instanceID)) { retrievedUsefulLinks = { usefulLinks: [ { url: SC.res['EnhancedHelp.GiveFeedback.Url'], title: SC.res['EnhancedHelp.GiveFeedback.Text'] }, ] }; retrievedNeedSupportsInfo = { needSupportLinks: [ { url: SC.res['EnhancedHelp.SubmitTicket.Url'], title: SC.res['EnhancedHelp.SubmitTicket.Text'] }, { url: SC.res['EnhancedHelp.StartChat.Url'], title: SC.res['EnhancedHelp.StartChat.Text'] }, ] }; retrievedAdditionalSupportLinksInfo = { additionalLinks: [ { url: SC.res['EnhancedHelp.OnlineHelp.Url'], title: SC.res['EnhancedHelp.OnlineHelp.Text'] }, { url: SC.res['EnhancedHelp.UserForum.Url'], title: SC.res['EnhancedHelp.UserForum.Text'] }, ] } } SC.dialog.showModalDialog('EnhancedHelp', { noBackdrop: true, isContentFullSize: true, titleResourceName: 'EnhancedHelp.ModalTitle.Text', content: [ $div({ className: 'GuidesPanel' }, [ createNewWindowLink('ReleaseNotes'), createNewWindowLink('SecurityGuide'), createNewWindowLink('SupportGuide'), createNewWindowLink('AccessGuide'), ]), $div( { className: 'HelpPanel TutorialsPanel', _visible: retrievedTutorialsInfo.tutorialLinks.length !== 0, }, [ $h4({ _textResource: 'EnhancedHelp.TutorialsPanel.Title' }), retrievedTutorialsInfo.tutorialLinks.map(function (tutorialInfo) { return $a({ href: tutorialInfo.url }, tutorialInfo.title); }), ] ), $div( { className: 'HelpPanel IdeasPanel', _visible: retrievedUsefulLinksInfo.usefulLinks.length !== 0, }, [ $h4({ _textResource: 'EnhancedHelp.IdeasPanel.Title' }), retrievedUsefulLinksInfo.usefulLinks.map(function (usefulLink) { return $a({ href: usefulLink.url }, usefulLink.title); }), ] ), $div( { className: 'HelpPanel NeedSupportPanel', _visible: retrievedNeedSupportsInfo.needSupportLinks.length !== 0, }, [ $h4({ _textResource: 'EnhancedHelp.NeedSupportPanel.Title' }), retrievedNeedSupportsInfo.needSupportLinks.map(function (needSupportLink) { return $a({ href: needSupportLink.url }, needSupportLink.title); }), ] ), $div({ className: 'MoreHelpPanel' }, retrievedAdditionalSupportLinksInfo.additionalLinks.map(function(additionalLink) { return $a({ href: additionalLink.url, target: '_blank' }, additionalLink.title); }) ), ], }); } break; } }); SC.event.addGlobalHandler(SC.event.PreRender, function (eventArgs) { if (SC.context.pageType == 'HostPage' || SC.context.pageType == 'AdministrationPage') { SC.util.includeStyleSheet(extensionContext.baseUrl + 'HelpStyle.css'); if (SC.context.productVersion.split('.')[0] < 20 || (SC.context.productVersion.split('.')[0] == 20 && SC.context.productVersion.split('.')[1] < 2)) { // New Solid Theme uses TrayIconPanel to show help icon in 20.2 if ($('link[href*="App_Themes"]').href.indexOf('Shell') == -1) { SC.ui.addContent( $('.NavigationPanel'), $div( { _commandName: 'ShowEnhancedHelp', className: 'EnhancedHelpButtonNavigationPanel', }, [ $img({ src: extensionContext.baseUrl + 'Icons/HelpIcon.svg' }), $span(SC.res['EnhancedHelp.ModalTitle.Text']), ] ) ); SC.ui.moveNodeUp($('.EnhancedHelpButtonNavigationPanel')); SC.ui.moveNodeUp($('.EnhancedHelpButtonNavigationPanel')); } } } }); });</script> <script>SC.extension.addInitializeProc('d6455ac7-fae5-4b37-8129-a7306f03d5bf', function (extensionContext) { SC.event.addGlobalHandler(SC.event.PreRender, function (eventArgs) { if (SC.context.isUserAdministrator && SC.context.pageType === 'AdministrationPage') SC.util.includeStyleSheet(extensionContext.baseUrl + 'TeamsIntegrationStyle.css'); }); function commandEventMatchesExtension(extensionContext, eventArgs) { return eventArgs && eventArgs.commandContext && eventArgs.commandContext.extensionInfo && extensionContext && extensionContext.baseUrl && extensionContext.baseUrl.endsWith(eventArgs.commandContext.extensionInfo.ExtensionID + '/'); } SC.event.addGlobalHandler(SC.event.QueryCommandButtons, function (eventArgs) { switch (eventArgs.area) { case 'ExtrasPopoutPanel': if (SC.context.pageType === "AdministrationPage") eventArgs.buttonDefinitions.push( { commandName: 'ShowTeamsConfigurationModal', text: SC.res['TeamsIntegration.ExtrasPopoutPanel.ButtonText'] } ); break; case 'OptionsPopoutPanel': if (commandEventMatchesExtension(extensionContext, eventArgs)) eventArgs.buttonDefinitions.push( { commandName: 'ShowTeamsConfigurationModal', text: SC.res['TeamsIntegration.ExtrasPopoutPanel.ButtonText'] } ); break; } }); SC.event.addGlobalHandler(SC.event.QueryCommandButtonState, function (eventArgs) { switch (eventArgs.commandName) { case 'EditExtensionSettings': if (commandEventMatchesExtension(extensionContext, eventArgs)) eventArgs.isVisible = false; break; } }); SC.event.addGlobalHandler(SC.event.ExecuteCommand, function (eventArgs) { switch (eventArgs.commandName) { case 'ShowTeamsConfigurationModal': showTeamsConfigurationModal(); break; } }); function showTeamsConfigurationModal () { SC.service.GetTeamsIntegrationSettings(function (teamsIntegrationSettings) { var webhookURIBox; SC.dialog.showModalButtonDialog( 'TeamsConfigurationModal', SC.res['TeamsIntegration.ConfigurationModal.TitleText'], SC.res['TeamsIntegration.ConfigurationModal.ButtonText'], 'Default', function (container) { SC.ui.setContents(container, [ $p({ innerHTML: SC.res['TeamsIntegration.ConfigurationModal.Instructions'], className: 'SettingHeader' }), $dl({}, [ $dt({ _textResource: 'TeamsIntegration.ConfigurationModal.WebhookUrlLabel' }), $dd({ className: 'TeamsConfigurationModalInput' }, webhookURIBox = SC.ui.createTextBox({ value : teamsIntegrationSettings["TeamsWebhookURI"] }, false, false, null)), $dt({ _textResource: 'TeamsIntegration.ConfigurationModal.SessionEventSelectorLabel' }), $dd({}, SC.ui.createMultiselectBox( "SessionEventTypes", teamsIntegrationSettings["SessionEventTypesIncludedOrExcluded"], teamsIntegrationSettings["SessionEventTypesFilter"], SC.types.SessionEventType, null, 'SessionEventMultiSelectBox' ) ), $dt({ _textResource: 'TeamsIntegration.ConfigurationModal.SecurityEventSelectorLabel' }), $dd({}, SC.ui.createMultiselectBox( "SecurityEventTypes", teamsIntegrationSettings['SecurityEventTypesIncludedOrExcluded'], teamsIntegrationSettings['SecurityEventTypesFilter'], SC.types.SecurityEventType, null, 'SecurityEventMultiSelectBox', 1 ) ), ]), $div({className: 'SecurityEventTimeRangeDiv'}, [ $input({ id: 'SecurityEventNotificationTimeRangeEnabled', type: 'checkbox', checked: teamsIntegrationSettings['SecurityEventNotificationTimeRangeEnabled'] }), $p({_textResource: 'TeamsIntegration.ConfigurationModal.SecurityEventTimeRangeTextBeginning'}), SC.ui.createTextBox({ className: 'TeamsIntegrationTimeInput', value: teamsIntegrationSettings['SecurityEventNotificationServerTimeRangeStart'], id: "SecurityEventNotificationServerTimeRangeStart" }, false, false, '09:00 AM'), $p({_textResource: 'TeamsIntegration.ConfigurationModal.SecurityEventTimeRangeTextMiddle'}), SC.ui.createTextBox({ className: 'TeamsIntegrationTimeInput', value: teamsIntegrationSettings['SecurityEventNotificationServerTimeRangeEnd'], id: "SecurityEventNotificationServerTimeRangeEnd" }, false, false, '05:00 PM'), $p({_textResource: 'TeamsIntegration.ConfigurationModal.SecurityEventTimeRangeTextEnd'}) ] ) ]); }, function (eventArgs, dialog, closeDialogProc, errorProc) { switch (eventArgs.commandName) { case 'Default': var sessionEventMultiSelectBoxValues = SC.ui.getValuesFromMultiselectBox($('.SessionEventMultiSelectBox')); var securityEventMultiSelectBoxValues = SC.ui.getValuesFromMultiselectBox($('.SecurityEventMultiSelectBox')); const timeRegex = /^(?:|((0?[1-9]|1[0-2]):([0-5][0-9]) ([AP]M)))$/i; var timeRangeStart = $('#SecurityEventNotificationServerTimeRangeStart').value; var timeRangeEnd = $('#SecurityEventNotificationServerTimeRangeEnd').value; if ( ($('#SecurityEventNotificationTimeRangeEnabled').checked && (!timeRangeStart || !timeRangeEnd)) || ((timeRangeStart && !timeRangeEnd) || (!timeRangeStart && timeRangeEnd)) ) { errorProc({ message: SC.res['TeamsIntegration.ConfigurationModal.EmptyTimesMessage'] }); } else if (!timeRegex.test(timeRangeStart) || !timeRegex.test(timeRangeEnd)) { errorProc({ message: SC.res['TeamsIntegration.ConfigurationModal.TimeFormatMessage'] }); } else { SC.service.SaveTeamsTriggerParameters( webhookURIBox.value, sessionEventMultiSelectBoxValues.includedOrExcludedValues, sessionEventMultiSelectBoxValues.includedOrExcluded, securityEventMultiSelectBoxValues.includedOrExcludedValues, securityEventMultiSelectBoxValues.includedOrExcluded, $('#SecurityEventNotificationTimeRangeEnabled').checked, $('#SecurityEventNotificationServerTimeRangeStart').value, $('#SecurityEventNotificationServerTimeRangeEnd').value, closeDialogProc, ); } break; } } ); }); } });</script> <script>SC.extension.addInitializeProc('13cde0ce-420d-410e-9ca2-053a5f237bb1', function (extensionContext) { SC.event.addGlobalHandler(SC.event.QueryTabContainsRelativeTimes, function (eventArgs) { if (isDiagnosticsTab(eventArgs.tabName)) eventArgs.hasRelativeTimes = true; }); SC.event.addGlobalHandler(SC.event.PreRender, function (eventArgs) { if (SC.context.pageType === 'HostPage') SC.util.includeStyleSheet(extensionContext.baseUrl + 'RemoteDiagnosticsToolkit.css'); }); SC.event.addGlobalHandler(SC.event.QueryCommandButtonState, function (eventArgs) { if (isDiagnosticsTab(eventArgs.commandArgument)) { eventArgs.isEnabled = eventArgs.isVisible = eventArgs.commandContext.sessionType === SC.types.SessionType.Access && eventArgs.commandContext && eventArgs.commandContext.sessions && eventArgs.commandContext.sessions.length === 1 && (eventArgs.commandContext.permissions & SC.types.SessionPermissions.RunCommandOutside) > 0 && (eventArgs.commandContext.permissions & SC.types.SessionPermissions.RemoveCommand) > 0 && !(eventArgs.commandArgument === 'RemoteDiagnosticToolkit.Users' && !extensionContext.custom.ShowUsersTab); } if (eventArgs.commandName === 'ExecuteRemoteCommand' && !extensionContext.custom.CanSendCommands && !(eventArgs.commandArgument === 'RemoveAdmin' && extensionContext.custom.ShowUsersTab)) { eventArgs.isEnabled = false; eventArgs.commandElement.parentElement.onmouseenter = function () { SC.tooltip.showPanel(eventArgs.commandElement.parentElement, SC.res['DiagnosticsToolkit.LicenseRestrictionTooltipMessage.Text']); }; eventArgs.commandElement.parentElement.onmouseleave = function () { SC.tooltip.hidePanel(); }; } }); SC.event.addGlobalHandler(SC.event.QueryCommandButtons, function (eventArgs) { switch (eventArgs.area) { case 'HostDetailTabList': Array.prototype.push.apply(eventArgs.buttonDefinitions, commandTabNameMap.map(function (it) { return { commandName: 'Select', commandArgument: it.tabName, text: SC.res['DiagnosticsToolkit.' + it.commandName + 'Tab.Label'], imageUrl: extensionContext.baseUrl + 'Images/Tab' + it.commandName + '.svg', tooltipOrTitle: true, }; // tooltipOrTitle is no longer need after live-data branch got merged in, keep this here for backward compatibility }) ); break; case 'DownloadLatestDiagnosticEventData': eventArgs.buttonDefinitions.push( { commandName: 'DownloadEventData', text: SC.res['DiagnosticsToolkit.DownloadData.Label'] } ); break; } }); SC.event.addGlobalHandler(SC.event.ExecuteCommand, function (eventArgs) { const dataItem = SC.util.combineObjects.apply(this, SC.command.getEventDataItems(eventArgs)); switch (eventArgs.commandName) { case 'RefreshDiagnostics': if (isSessionGuestConnected(dataItem.session)) { executeRemoteCommand("Get" + dataItem.commandName, null, dataItem.session.GuestOperatingSystemName, dataItem.SessionID); setLoadingIndicator(true); } break; case 'ExecuteRemoteCommand': if (isSessionGuestConnected(dataItem.session)) { executeRemoteCommand(eventArgs.commandArgument, dataItem.itemData, dataItem.session.GuestOperatingSystemName, dataItem.SessionID); setLoadingIndicator(true); SC.css.ensureClass(SC.command.getEventDataElement(eventArgs), 'Loading', true); } break; case 'DownloadEventData': var dt = new Date(); var link = $a({ download: SC.util.formatString(SC.res['DiagnosticsToolkit.DownloadData.FileNameFormat'], dataItem.session.Name, dataItem.commandName, dt.toLocaleDateString(), dt.toLocaleTimeString()), href: 'data:text/plain,' + window.encodeURIComponent(dataItem.eventParseResult.rawContent), }); document.body.appendChild(link); link.click(); document.body.removeChild(link); break; } }); SC.event.addGlobalHandler(SC.event.InitializeTab, function (eventArgs) { if (isDiagnosticsTab(eventArgs.tabName)) { SC.ui.setContents(eventArgs.container, [ $div({ className: 'DiagnosticsHeader' }, [ $h2(SC.res['DiagnosticsToolkit.' + getDiagnosticsTabCommandName(eventArgs.tabName) + 'Tab.Label']), $div({ className: 'LastUpdatePanel' }, [ $span({ className: 'LastUpdateTime' }), SC.command.createCommandButtons([{ commandName: 'RefreshDiagnostics', text: SC.res['DiagnosticsToolkit.Refresh.Button'] }]) ]), $div({ className: 'FilterBoxPanel' }, SC.ui.createFilterBox({ id: 'diagnosticsFilterBox' }, function () { applyFilter(eventArgs.container); }), ), ]), $div({ className: 'InformationDisplayContainer' }, extensionContext.custom.CanSendCommands || (extensionContext.custom.ShowUsersTab && eventArgs.tabName === 'RemoteDiagnosticToolkit.Users') ? null : $div({className: 'RDTLicenseRestrictionContainer'}, [ $img({className: 'RDTShoppingBagIcon', src: extensionContext.baseUrl + 'Images/shopping-bag-icon.png'}), $p({_innerHTMLToBeSanitized: SC.res['DiagnosticsToolkit.LicenseRestrictionMessage.Text']}) ]), $div({ className: 'EmptyPanel' }, getEmptyStateContents(eventArgs.tabName) ), $table({ className: 'DataTable' }) ), $div({ className: 'DownloadButtonPanel' }, [ $div({ className: 'DownloadDataButton' }, SC.command.queryAndCreateCommandButtons('DownloadLatestDiagnosticEventData')) ]) ]); setLoadingIndicator(true); } }); SC.event.addGlobalHandler(SC.event.RefreshTab, function (eventArgs) { if (isDiagnosticsTab(eventArgs.tabName)) { var isGuestConnected = isSessionGuestConnected(eventArgs.session); var tryDeleteEvents = function (eventCollection, eventType, shouldDeleteFunc) { if (eventCollection) eventCollection.forEach(function (item, i) { if (shouldDeleteFunc(item, i)) { SC.service.DeleteDiagnosticCommandEvents( eventArgs.session.SessionID, item.ConnectionID || null, item.EventID, eventType ); } }); }; var getQueuedEvents = function (parseResultPredicate) { return eventArgs.sessionDetails.Events .filter(function (e) { return e.EventType === SC.types.SessionEventType.QueuedCommand; }) .filter(function (e) { return parseResultPredicate(parseQueuedCommandEvent(e.Data)); }) .sort(function (x, y) { return x.Time - y.Time; }); }; var diagnosticEventPredicate = function (it) { return it.isValid && it.headers.Command === "Get" + getDiagnosticsTabCommandName(eventArgs.tabName); }; var invalidatingEventPredicate = function (it) { return it.isValid && it.headers && it.headers['InvalidatesCommand']; }; var queuedDiagnosticEvents = getQueuedEvents(diagnosticEventPredicate); var latestQueuedDiagnosticEvent = queuedDiagnosticEvents.length > 0 ? queuedDiagnosticEvents[0] : null; var queuedInvalidatingEvents = getQueuedEvents(invalidatingEventPredicate); var latestQueuedInvalidatingEvent = queuedInvalidatingEvents.length > 0 ? queuedInvalidatingEvents[0] : null; var versionParts = SC.context.productVersion.split('.'); if (versionParts && versionParts.length > 1) { var ranEvents; if (SC.util.isVersion({ major: 22, minor: 9 }, null, { major: versionParts[0], minor: versionParts[1] })) { ranEvents = eventArgs.sessionDetails.Events .filter(function (e) { if (e.ConnectionID !== null && e.EventType == SC.types.SessionEventType.RanCommand) { var parseResult = parseRanCommandEvent(e.Data, 1); return parseResult.isValid; } return false; }); } else { ranEvents = eventArgs.sessionDetails.Connections .map(function (c) { Array.prototype.forEach.call(c.Events, function (e) { e.ConnectionID = c.ConnectionID; }); return c.Events; }) .reduce(function (outputArray, events) { Array.prototype.push.apply(outputArray, events); return outputArray; }, []) .filter(function (e) { if (e.EventType === SC.types.SessionEventType.RanCommand) { var parseResult = parseRanCommandEvent(e.Data, 1); return parseResult.isValid; } return false; }); } } var getRanEvents = function (parseResultPredicate) { return ranEvents .filter(function (e) { return parseResultPredicate(parseRanCommandEvent(e.Data, 1)); }) .sort(function (x, y) { return x.Time - y.Time; }); }; var ranDiagnosticEvents = getRanEvents(diagnosticEventPredicate); var latestRanDiagnosticEvent = ranDiagnosticEvents.length > 0 ? ranDiagnosticEvents[0] : null; var ranInvalidatingEvents = getRanEvents(invalidatingEventPredicate); var latestRanInvalidatingEvent = ranInvalidatingEvents.length > 0 ? ranInvalidatingEvents[0] : null; var latestRanDiagnosticEventParseResult = latestRanDiagnosticEvent ? parseRanCommandEvent(latestRanDiagnosticEvent.Data, 2) : null; var isParseResultValid = latestRanDiagnosticEventParseResult && latestRanDiagnosticEventParseResult.isValid; eventArgs.container._dataItem = { commandName: getDiagnosticsTabCommandName(eventArgs.tabName), event: latestRanDiagnosticEvent, session: eventArgs.session, eventParseResult: latestRanDiagnosticEventParseResult, }; setLoadingIndicator(!latestRanDiagnosticEvent || latestQueuedDiagnosticEvent || latestRanInvalidatingEvent || latestQueuedInvalidatingEvent); var informationDisplayContainer = eventArgs.container.querySelector('.InformationDisplayContainer'); SC.css.ensureClass(informationDisplayContainer, 'Empty', !latestRanDiagnosticEvent || !isParseResultValid); SC.ui.setVisible($('.FilterBoxPanel'), latestRanDiagnosticEvent && isParseResultValid); if (isGuestConnected && (!latestQueuedDiagnosticEvent || latestQueuedDiagnosticEvent.Time > 45000) && (!latestRanDiagnosticEvent || (latestRanInvalidatingEvent && latestRanInvalidatingEvent.Time < latestRanDiagnosticEvent.Time) || (latestRanDiagnosticEvent.Time > 300000) ) ) { executeRemoteCommand('Get' + getDiagnosticsTabCommandName(eventArgs.tabName), null, eventArgs.session.GuestOperatingSystemName, eventArgs.session.SessionID); setLoadingIndicator(true); } var ranCommandInfos = ranEvents .map(function (ranEvent) { return { time: ranEvent.Time, parseResult: parseRanCommandEvent(ranEvent.Data, 1), }; }) .filter(function (eventInfo) { return eventInfo.parseResult.isValid && eventInfo.parseResult.headers && eventInfo.parseResult.headers.Command && eventInfo.parseResult.headers.CommandKey; }) .map(function (eventInfo) { return { ranEventTime: eventInfo.time, command: eventInfo.parseResult.headers.Command, commandKey: eventInfo.parseResult.headers.CommandKey, }; }); var unshownCommandInfos = eventArgs.sessionDetails.Events .filter(function (it) { return it.EventType === SC.types.SessionEventType.QueuedCommand; }) .map(function (queuedCommandEvent) { return { id: queuedCommandEvent.EventID, time: queuedCommandEvent.Time, parseResult: parseQueuedCommandEvent(queuedCommandEvent.Data), }; }) .filter(function (eventInfo) { return eventInfo.parseResult.isValid && eventInfo.parseResult.headers && eventInfo.parseResult.headers.Command && eventInfo.parseResult.headers.CommandKey && eventInfo.parseResult.headers.CommandKeyIndices; }) .map(function (eventInfo) { return { queuedEventID: eventInfo.id, queuedEventTime: eventInfo.time, command: eventInfo.parseResult.headers.Command, commandKey: eventInfo.parseResult.headers.CommandKey, commandKeyIndices: eventInfo.parseResult.headers.CommandKeyIndices, }; }) .filter(function (commandInfo) { return !latestRanDiagnosticEvent || latestRanDiagnosticEvent.Time >= commandInfo.queuedEventTime || !ranCommandInfos.some(function (ranCommandInfo) { return ranCommandInfo.command === commandInfo.command && ranCommandInfo.commandKey === commandInfo.commandKey && ranCommandInfo.ranEventTime < commandInfo.queuedEventTime && ranCommandInfo.ranEventTime >= latestRanDiagnosticEvent.Time; }); }); tryDeleteEvents( queuedDiagnosticEvents, SC.types.SessionEventType.QueuedCommand, function (queuedDiagnosticEvent, i) { return i > 0 || latestRanDiagnosticEvent && latestRanDiagnosticEvent.Time < queuedDiagnosticEvent.Time; } ); tryDeleteEvents( queuedInvalidatingEvents, SC.types.SessionEventType.QueuedCommand, function (queuedInvalidatingEvent) { return !unshownCommandInfos.some(function (unshownCommandInfo) { return unshownCommandInfo.queuedEventID === queuedInvalidatingEvent.EventID; }); } ); tryDeleteEvents( ranInvalidatingEvents, SC.types.SessionEventType.RanCommand, function (ranInvalidatingEvent, i) { if (i == 0 && (!latestRanDiagnosticEvent || latestRanDiagnosticEvent.Time >= ranInvalidatingEvent.Time)) return false; var ranInvalidatingEventParseResult = parseRanCommandEvent(ranInvalidatingEvent.Data, 1); return !ranInvalidatingEventParseResult.isValid || !ranInvalidatingEventParseResult.headers || !ranInvalidatingEventParseResult.headers.Command || !ranInvalidatingEventParseResult.headers.CommandKey || !unshownCommandInfos.some(function (unshownCommandInfo) { return unshownCommandInfo.command === ranInvalidatingEventParseResult.headers.Command && unshownCommandInfo.commandKey === ranInvalidatingEventParseResult.headers.CommandKey && unshownCommandInfo.queuedEventTime >= ranInvalidatingEvent.Time; }); } ); tryDeleteEvents(ranDiagnosticEvents, SC.types.SessionEventType.RanCommand, function (ranDiagnosticEvent, i) { return i > 0; }); if (latestRanDiagnosticEvent && isParseResultValid) { eventArgs.container.querySelector('.LastUpdateTime').innerHTML = "Updated " + SC.util.formatSecondsDuration(latestRanDiagnosticEvent.Time / 1000) + " ago"; var buttonDefinitions = getButtonDefinitions(latestRanDiagnosticEventParseResult); var unavailableCommandsColumnIndex = latestRanDiagnosticEventParseResult.columnNames.findIndex(c => c == 'UnavailableCommands'); SC.css.ensureClass($('.InformationDisplayContainer .DataTable'), 'NoActionCellDataTable', buttonDefinitions.length === 0); if (latestRanDiagnosticEventParseResult.data) { var hiddenColumnIndices = latestRanDiagnosticEventParseResult.headers && latestRanDiagnosticEventParseResult.headers['HiddenColumnIndices'] ? latestRanDiagnosticEventParseResult.headers['HiddenColumnIndices'].split(',').map(function (index) { return +index; }) : []; // It would have been ideal to do all the styling in the RemoteDiagnosticsToolkit.css // file. However, since we do not have access to the required variables, like // the $shade1BackgroundColor, whose value changes depending on the theme, over there, // we had to do the styling in JavaScript so that we can programmatically determine // their correct (theme-based) values. var desiredBackgroundColor = ''; SC.ui.findAncestor(informationDisplayContainer, function (currentElement) { var defaultBackgroundColor = 'rgba(0, 0, 0, 0)'; var currentElementBackgroundColor = window.getComputedStyle(currentElement).backgroundColor; if (currentElementBackgroundColor !== defaultBackgroundColor) { desiredBackgroundColor = currentElementBackgroundColor; return true; } return false; }); informationDisplayContainer.style.background = SC.util.formatString( 'linear-gradient({0} 70%, hsla(0, 0%, 100%, 0)), ' + 'linear-gradient(hsla(0, 0%, 100%, 0) 10px, {0} 30%), ' + 'radial-gradient(at top, rgba(0, 0, 0, 0.2), transparent 70%), ' + 'radial-gradient(at bottom, rgba(0, 0, 0, 0.2), transparent 70%)', desiredBackgroundColor ); informationDisplayContainer.style.backgroundRepeat = 'no-repeat'; informationDisplayContainer.style.backgroundSize = '100% 50px, 100% 50px, 100% 10px, 100% 10px'; informationDisplayContainer.style.backgroundPosition = 'left top, right bottom, left 0px top 23px, right bottom'; informationDisplayContainer.style.backgroundAttachment = 'local, local, scroll, scroll'; informationDisplayContainer.style.backgroundColor = desiredBackgroundColor; var tableHeaderCellCssText = SC.util.formatString('background-color: {0}; background-clip: padding-box; opacity: 1.0;', desiredBackgroundColor); SC.ui.setContents(eventArgs.container.querySelector('table'), [ $tr( $th({ className: 'ActionCell HeaderCell', _cssText: tableHeaderCellCssText }), latestRanDiagnosticEventParseResult.columnNames .filter(function (it, index) { return !hiddenColumnIndices.some(function (hiddenIndex) { return hiddenIndex === index; }); }) .map(function (columnName) { return $th({ className: 'HeaderCell', _cssText: tableHeaderCellCssText }, columnName); }) ), latestRanDiagnosticEventParseResult.data.map(function (itemData) { return $tr({ _dataItem: { itemData: itemData }, _classNameMap: { 'Loading': unshownCommandInfos.some(function (unshownCommandInfo) { return unshownCommandInfo.commandKey === unshownCommandInfo .commandKeyIndices .split(',') .map(function (index) { return itemData[+index]; }) .join(''); }), }, }, [ $td({ className: 'ActionCell' }, SC.command.createCommandButtons(filterUnavailableCommands(unavailableCommandsColumnIndex, itemData, buttonDefinitions))), itemData .filter(function (it, index) { return !hiddenColumnIndices.some(function (hiddenIndex) { return hiddenIndex === index; }); }) .map(function (cellData) { return $td(cellData); }), ]); }), ]); } applyFilter(eventArgs.container); } else { SC.ui.setContents( eventArgs.container.querySelector('.EmptyPanel'), getEmptyStateContents(eventArgs.tabName, isGuestConnected, isParseResultValid) ); if (!isGuestConnected) setLoadingIndicator(false); } } }); var commandTabNameMap = ['Processes', 'Software', 'EventLog', 'Services', 'Updates', 'Users'].map(function (it) { return { commandName: it, tabName: 'RemoteDiagnosticToolkit.' + it }; }); function isDiagnosticsTab(tabName) { return commandTabNameMap.find(function (it) { return it.tabName === tabName; }) ? true : false; } function getDiagnosticsTabCommandName(tabName) { return commandTabNameMap.find(function (it) { return it.tabName === tabName; }).commandName; } function getEmptyStateContents(tabName, isGuestConnected = true, isParseResultValid = true) { var tabCommandName = getDiagnosticsTabCommandName(tabName); return [ $p( $img({ src: extensionContext.baseUrl + 'Images/' + tabCommandName + 'Empty.png', }) ), $h2({ innerHTML: getEmptyStateTitle(tabCommandName, isGuestConnected, isParseResultValid) }), $p({ innerHTML: getEmptyStateText(tabCommandName, isGuestConnected, isParseResultValid) }) ]; } function getEmptyStateTitle(tabCommandName, isGuestConnected, isParseResultValid) { var tabLabel = SC.res['DiagnosticsToolkit.' + tabCommandName + 'Tab.Label']; return isGuestConnected && isParseResultValid ? SC.util.formatString( '{0} {1}', tabLabel, SC.res["DiagnosticsToolkit.EmptyTab.TitleLoadingSuffix"] ) : SC.util.formatString( '{0} {1} {2}', SC.res['DiagnosticsToolkit.EmptyTab.TitlePrefix'], tabLabel, SC.res['DiagnosticsToolkit.EmptyTab.TitleSuffix'] ); } function getEmptyStateText(tabCommandName, isGuestConnected, isParseResultValid) { if (isGuestConnected) { return isParseResultValid ? SC.util.formatString(SC.res['DiagnosticsToolkit.EmptyTab.TextFormat'], SC.res['DiagnosticsToolkit.' + tabCommandName + 'Tab.Label']) : SC.res['DiagnosticsToolkit.EmptyTab.ParseErrorText']; } else { return SC.res['DiagnosticsToolkit.EmptyTab.GuestNotConnectedText']; } } function isSessionGuestConnected(session) { return session && session.ActiveConnections && session.ActiveConnections.length > 0 ? session.ActiveConnections.some(function (it) { return it.ProcessType === SC.types.ProcessType.Guest; }) : false; } function applyFilter(container) { var valueUpper = container.querySelector("input").value.toUpperCase(); var table = container.querySelector("table"); Array.from(table.children).forEach((it, index) => SC.ui.setVisible(it, index === 0 || it.innerHTML.toUpperCase().includes(valueUpper))); } function setLoadingIndicator(addOrRemove) { var element = $('.LastUpdatePanel a'); if (element) SC.css.ensureClass(element, 'LoadingIndicatorRight', addOrRemove); } function getButtonDefinitions(parseResult) { var availableCommands = parseResult.headers && parseResult.headers['AvailableCommands'] ? parseResult.headers['AvailableCommands'].split(',') : []; var buttonDefinitions = Array(); if (availableCommands && availableCommands.length > 0) { for (var i = 0; i < availableCommands.length; i++) buttonDefinitions.push({ commandName: 'ExecuteRemoteCommand', commandArgument: availableCommands[i], text: SC.res['DiagnosticsToolkit.MachineInteraction.' + availableCommands[i]], }); } return buttonDefinitions; } function filterUnavailableCommands(unavailableCommandsColumnIndex, itemData, buttonDefinitions) { var filteredButtonDefinitions = buttonDefinitions; if (itemData[unavailableCommandsColumnIndex] && itemData[unavailableCommandsColumnIndex] != '') filteredButtonDefinitions = buttonDefinitions.filter(function (buttonDefinition) { return !itemData[unavailableCommandsColumnIndex].includes('|' + buttonDefinition.commandArgument + '|'); }); return filteredButtonDefinitions; } function executeRemoteCommand(remoteCommandName, itemData, operatingSystemName, sessionID) { var osType = operatingSystemName.indexOf("Windows") >= 0 || operatingSystemName.indexOf("Server") >= 0 ? "Windows" : operatingSystemName.indexOf("Linux") >= 0 ? "Linux" : operatingSystemName.indexOf("Mac") >= 0 ? "OSX" : "Unknown"; var commandInfo = getCommandInfo(remoteCommandName, itemData, osType); var emptyLinePrefix, delimiter, modifier; if (commandInfo.processor === 'sh') { modifier = "echo "; delimiter = ''; emptyLinePrefix = 'echo '; } else { modifier = "echo \""; delimiter = '\"'; emptyLinePrefix = 'echo ""'; } var eventData = "#!" + commandInfo.processor + "\n" + "#maxlength=50000000" + "\n" + "#timeout=900000" + "\n" + "#DIAGNOSTIC-REQUEST/2" + "\n" + "#Command: " + remoteCommandName + "\n" + "#CommandKeyIndices: " + (commandInfo.commandKeyIndices ? commandInfo.commandKeyIndices.join(',') : "") + "\n" + "#CommandKey: " + (commandInfo.commandKey || "") + "\n" + "#AvailableCommands: " + "\n" + "#InvalidatesCommand: " + (commandInfo.invalidatesCommand || "") + "\n" + "#HiddenColumnIndices: " + "\n" + modifier + "DIAGNOSTIC-RESPONSE/2" + delimiter + "\n" + modifier + "Command: " + remoteCommandName + delimiter + "\n" + modifier + "CommandKeyIndices: " + (commandInfo.commandKeyIndices ? commandInfo.commandKeyIndices.join(',') : "") + delimiter + "\n" + modifier + "CommandKey: " + (commandInfo.commandKey || "") + delimiter + "\n" + modifier + "ContentType: " + commandInfo.contentType + delimiter + "\n" + modifier + "AvailableCommands: " + (commandInfo.availableCommands ? commandInfo.availableCommands.join(",") : "") + delimiter + "\n" + modifier + "InvalidatesCommand: " + (commandInfo.invalidatesCommand ? commandInfo.invalidatesCommand : "") + delimiter + '\n' + modifier + "HiddenColumnIndices: " + (commandInfo.hiddenColumnIndices ? commandInfo.hiddenColumnIndices.join(',') : "") + delimiter + '\n' + emptyLinePrefix + "\n" + commandInfo.commandText; SC.service.AddDiagnosticEventToSession(sessionID, eventData); } function parseQueuedCommandEvent(content) { var parseResult = { isValid: content.startsWith("#!") && content.indexOf("DIAGNOSTIC-REQUEST/2") !== -1, }; if (parseResult.isValid) { parseResult.headers = {}; forEachTrimmedLine(content, function (line) { if (line.startsWith('#')) { var lineParts = line.substring(1).split(':'); if (lineParts.length > 1) parseResult.headers[lineParts[0].trim()] = lineParts[1] ? lineParts[1].trim() : ''; } }); } return parseResult; } function parseRanCommandEvent(content, parseLevel) { var parseResult = { isValid: content.startsWith("DIAGNOSTIC-RESPONSE/2"), // don't bother with that bug BOM }; if (parseResult.isValid && parseLevel >= 1) { parseResult.headers = {}; var contentStartCharIndex = forEachTrimmedLine(content, function (line, lineIndex) { if (line === '') { return true; } else if (lineIndex >= 1) { // ignore status line var lineParts = line.split(':'); parseResult.headers[lineParts[0].trim()] = lineParts[1] ? lineParts[1].trim() : ''; } }); if (parseLevel >= 2) { parseResult.rawContent = content.substring(contentStartCharIndex); if (parseResult.headers.ContentType === 'xml') { var document = getXmlDocument(parseResult.rawContent); if (document) { var objectElements = document.getElementsByTagName("Object"); if (objectElements[0]) { parseResult.columnNames = Array.from(objectElements[0].children).map(function (columnElement) { return columnElement.attributes['Name'].value; }); parseResult.data = Array.from(objectElements).map(function (objectElement) { return Array.from(objectElement.children).map(function (columnElement) { return columnElement.innerHTML; }); }); } else { parseResult.isValid = false; } } } else if (parseResult.headers.ContentType === 'text') { forEachTrimmedLine(parseResult.rawContent, function (line, lineIndex) { var values = line.split(',').map(function (it) { return it.trim(); }); if (lineIndex === 0) { parseResult.columnNames = values; } else { if (lineIndex === 1) parseResult.data = []; parseResult.data.push(values); } }); } } } return parseResult; } function forEachTrimmedLine(text, doLineUntilFunc) { var currentCharIndex = 0; var lineIndex = 0; while (true) { var nextNewLineCharIndex = text.indexOf('\n', currentCharIndex); if (nextNewLineCharIndex === -1) break; var line = text.substring(currentCharIndex, nextNewLineCharIndex).trim(); // trim \r among other things currentCharIndex = nextNewLineCharIndex + 1; if (doLineUntilFunc(line, lineIndex++)) break; } return currentCharIndex; } function getXmlDocument(xmlText) { if (window.DOMParser) { try { return (new DOMParser()).parseFromString(xmlText, "text/xml"); } catch (e) { } } if (!document && window.ActiveXObject) { try { var document = new ActiveXObject('Microsoft.XMLDOM'); document.async = false; if (!document.loadXML(xmlText)) throw "malformed xml"; return document; } catch (e) { } } } function quoteForPowerShell(string) { var escapedItemData = string.replaceAll("'", "''"); return "'" + escapedItemData + "'"; } function parseMsiExecuteCommand(uninstallString, identifyingNumber) { var expression = new RegExp("\\/[XxIi][ ]*" + identifyingNumber, ''); return uninstallString.replace(expression, '/x "' + identifyingNumber + '" /q'); } function getCommandInfo(remoteCommandName, itemData, osType) { var getCommandTextForLinuxDistributionBasedExecution = function (commandTextForRedHatDistributions, commandTextForDebianDistributions) { return SC.util.formatString( "if which rpm >/dev/null 2>&1; then {0}; elif which dpkg >/dev/null 2>&1; then {1}; fi", commandTextForRedHatDistributions, commandTextForDebianDistributions ); } switch (remoteCommandName + '/' + osType) { case "GetProcesses/Windows": return { processor: 'ps', contentType: 'xml', hiddenColumnIndices: [], availableCommands: ['KillProcess'], commandText: "$Ram = Get-WMIObject Win32_PhysicalMemory | Measure -Property Capacity -Sum | %{$_.Sum}; Get-Process | Select @{N='ID';E={$_.Id}}, @{N='Process Name';E={$_.ProcessName}}, @{N='Memory (%)';E={[string]::Format(\"{0:p}\", $_.WorkingSet64/$Ram)}}, @{N='Memory (KB)';E={[string]::Format(\"{0:N0}\", $_.WorkingSet64/1024)}}, WS | Sort -Descending WS | Select 'ID', 'Process Name', 'Memory (%)', 'Memory (KB)' | ConvertTo-Xml -As Stream" }; case "GetEventLog/Windows": return { processor: 'ps', contentType: 'xml', hiddenColumnIndices: [], availableCommands: [], commandText: SC.util.formatString("Get-EventLog Application -newest {0} | Select @{N='Time Written';E={$_.TimeWritten}}, @{N='Entry Type';E={$_.EntryType}}, @{N='Source';E={$_.Source}}, @{N='Event ID';E={$_.EventID}}, @{N='Message';E={$_.Message}} | Sort 'Time Written' -Descending | ConvertTo-Xml -As Stream | ForEach-Object { $_ -replace '>\\s+<', '><' }", SC.util.getBoundedValue(1, extensionContext.settingValues.EventLogRequestCount, 500)) }; case "GetServices/Windows": return { processor: 'ps', contentType: 'xml', hiddenColumnIndices: [], availableCommands: ['StopService', 'StartService', 'RestartService'], commandText: "Get-Service | Select @{N='Name';E={$_.Name}}, @{N='Display Name';E={$_.DisplayName}}, @{N='Status';E={$_.Status}}, @{N='Startup Type';E={$_.StartType}} | Sort 'Display Name' | ConvertTo-Xml -As Stream" }; case "GetSoftware/Windows": return { processor: 'ps', contentType: 'xml', hiddenColumnIndices: [0, 4, 6], availableCommands: ['UninstallSoftware'], commandText: "$registryPath = if ([Environment]::Is64BitOperatingSystem) { 'HKLM:\\Software\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\*', 'HKLM:\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\*' } else { 'HKLM:\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\*' } Get-ItemProperty $registryPath | Where-Object{![string]::IsNullOrEmpty($_.DisplayName)} | Select @{N='IdentifyingNumber';E={$_.PSChildName}}, @{N='Name';E={$_.DisplayName}}, @{N='Vendor';E={$_.Publisher}}, @{N='Version';E={$_.DisplayVersion}}, @{N='UninstallString';E={$_.UninstallString}}, @{N='Install Date';E={If ($_.InstallDate) { [datetime]::ParseExact($_.InstallDate, 'yyyyMMdd', $null).ToString('yyyy-MM-dd') } Else { $null }}}, @{N='UnavailableCommands';E={$(If (![string]::IsNullOrEmpty($_.UninstallString) -and $_.UninstallString.ToLower() -like 'msiexec*') {''} Else {'|UninstallSoftware|'})}} | Sort 'Name' | ConvertTo-Xml -As Stream" }; case "GetUpdates/Windows": return { processor: 'ps', contentType: 'xml', hiddenColumnIndices: [0], availableCommands: ['InstallUpdate'], commandText: "$UpdateSession = New-Object -ComObject Microsoft.Update.Session" + "\n" + "$UpdateSearcher = $UpdateSession.CreateUpdateSearcher()" + "\n" + "$Updates = @($UpdateSearcher.Search(\"IsHidden=0\").Updates)" + "\n" + "$Updates | Where-Object { !$_.IsInstalled } | Select-Object @{N='UpdateID';E={$_.Identity.UpdateID}}, @{N='Title';E={$_.Title}}, @{N='Downloaded';E={$_.IsDownloaded}}, @{N='Installed';E={$_.IsInstalled}}, @{N='Date Published'; E={[string]::Format(\"{0:d}\", $_.LastDeploymentChangeTime)}} | ConvertTo-Xml -As Stream" }; case "GetUsers/Windows" : return { processor: 'ps', contentType: 'xml', hiddenColumnIndices: [4], availableCommands: ['RemoveAdmin'], commandText: "$users = @{}; Get-WmiObject Win32_UserAccount -Filter \"LocalAccount=True\" | % {$enabled = if ($_.Disabled) {\"False\"} else {\"True\"}; $camUser = if ($_.Description -eq \"[EPHEMERAL_USER_DO_NOT_REMOVE_THIS_UNLESS_DESIRED_PERMANENT]\") {$true} else {$false}; $objectProperties = @{Name = $_.Name; Domain = \"Local\"; Groups = @(); GroupString = \"\"; Enabled = $enabled; CamUser = $camUser}; $newUser = New-Object PSObject -Property $objectProperties; $users.Add($_.Name, $newUser)}; Get-WmiObject Win32_Group -Filter \"LocalAccount=True\" | % {$query = \"GroupComponent=`\"Win32_Group.Domain='$($_.Domain)',Name='$($_.Name)'`\"\"; $groupusers = Get-WmiObject Win32_GroupUser -Filter $query | select GroupComponent, PartComponent | Where-Object { $_.PartComponent -like \"*Win32_UserAccount*\" }; foreach ($groupuser in $groupusers) {$name = \"\"; $domain = \"\"; $enabled = \"N/A\"; if ($groupuser.PartComponent -match 'Name=\"([^\"]+)\"') {$name = $matches[1]} if ($groupuser.PartComponent -match 'Domain=\"([^\"]+)\"') {if ($matches[1] -ceq $env:COMPUTERNAME) {$domain = \"Local\"; $enabled = \"False\"} else {$domain = $matches[1]}} if($users.ContainsKey($name)) {$users[$name].Groups += $_.Name; if ($users[$name].Groups.Length -eq 1) {$users[$name].GroupString += $_.Name} else {$users[$name].GroupString += \", \" + $_.Name}} else {$objectProperties = @{Name = $name; Domain = $domain; Groups = @($_.Name); GroupString = \"\" + $_.Name; Enabled = $enabled; CamUser = $false}; $newUser = New-Object PSObject -Property $objectProperties; $users.Add($name, $newUser)}}}; Get-WmiObject Win32_UserProfile | % {$userProfile = \"\"; if ($_.LocalPath -match 'Users\\\\(.+)') {$userProfile = $matches[1]; if (-not $users.ContainsKey($userProfile)) {$objectProperties = @{Name = $userProfile; Domain = \"-\"; Groups = @(); GroupString = \"-\"; Enabled = \"N/A\"; CamUser = $false}; $newUser = New-Object PSObject -Property $objectProperties; $users.Add($userProfile, $newUser)}}}; $disabledUsers = $users.Values | Where { $_.Enabled -eq \"False\" } | Sort -Property Name; $otherUsers = $users.Values | Where { $_.Enabled -ne \"False\" } | Sort -Property Name; $combinedUsers = @($otherUsers) + @($disabledUsers); $combinedUsers | Where {-not $_.CamUser} | Select @{N='Name';E={$_.Name}}, @{N='Domain';E={$_.Domain}}, @{N='Local Groups';E={$_.GroupString}}, @{N='Enabled';E={$_.Enabled}}, @{N='UnavailableCommands';E={$(If ($_.Groups -contains \"Administrators\") {''} Else {'|RemoveAdmin|'})}} | ConvertTo-Xml -As Stream"}; case "GetProcesses/Linux": return { processor: 'sh', contentType: 'text', hiddenColumnIndices: [], availableCommands: ['KillProcess'], commandText: "ps -eo \"user,pid,time,pcpu,pmem,comm\" --sort -pmem | awk \'{print $1,\",\"$2,\",\"$3,\",\"$4,\",\"$5,\",\"$6 }\'" }; case "GetEventLog/Linux": return { processor: 'sh', contentType: 'text', hiddenColumnIndices: [], availableCommands: [], commandText: SC.util.formatString("echo Event Log Entry ; dmesg -T | tail -{0}", SC.util.getBoundedValue(1, extensionContext.settingValues.EventLogRequestCount, 500)) }; case "GetServices/Linux": return { processor: 'sh', contentType: 'text', hiddenColumnIndices: [], availableCommands: ['StopService', 'StartService', 'RestartService'], commandText: "echo Service Name ; ls /etc/init.d" }; case "GetSoftware/Linux": return { processor: 'sh', contentType: 'text', hiddenColumnIndices: [], availableCommands: ['UninstallSoftware'], commandText: SC.util.formatString("echo Application Name ; {0}", getCommandTextForLinuxDistributionBasedExecution("rpm --query --all --queryformat \"%{NAME}\\n\"", "dpkg --get-selections | awk '$2 == \"install\" { print $1 }'")) }; case "GetProcesses/OSX": return { processor: 'sh', contentType: 'text', hiddenColumnIndices: [], availableCommands: ['KillProcess'], commandText: "ps -eo \"user,pid,time,pcpu,pmem,comm\" -m | awk \'{print $1,\",\"$2,\",\"$3,\",\"$4,\",\"$5,\",\"$6 }\'" }; case "GetEventLog/OSX": return { processor: 'sh', contentType: 'text', hiddenColumnIndices: [], availableCommands: [], commandText: SC.util.formatString("echo Event Log Entry ; log show --style syslog -last 500 | tail -n {0}", SC.util.getBoundedValue(1, extensionContext.settingValues.EventLogRequestCount, 500)) }; case "GetServices/OSX": return { processor: 'sh', contentType: 'text', hiddenColumnIndices: [1], availableCommands: ['StartService', 'RestartService'], commandText: "headersText=$(echo \"Service Name\\t,Owner\";) && systemServices=$(ls /Library/LaunchDaemons | sed 's/\\.plist$//' | sed 's|$|\\t,system|') && userServices=$(ls /Library/LaunchAgents | sed 's/\\.plist$//' | sed 's|$|\\t,user|') && userId=$(stat -f '%u' /dev/console | grep -vx 0); if [[ $userId -ne 0 ]]; then" + "\n" + " echo \"$headersText\"; echo \"$systemServices\"; echo \"$userServices\";" + "\n" + "else" + "\n" + " echo \"$headersText\"; echo \"$systemServices\";" + "\n" + "fi", }; case "GetSoftware/OSX": return { processor: 'sh', contentType: 'text', hiddenColumnIndices: [], availableCommands: [], commandText: "echo Application Name; ls /Applications" }; case "KillProcess/Linux": return { processor: 'sh', invalidatesCommand: 'GetProcesses', commandKeyIndices: [1], commandKey: itemData[1], commandText: SC.util.formatString("kill {0}", typeof itemData[1] == 'string' ? quoteForPowerShell(itemData[1]) : '') }; case "KillProcess/OSX": return { processor: 'sh', invalidatesCommand: 'GetProcesses', commandKeyIndices: [1], commandKey: itemData[1], commandText: SC.util.formatString("kill {0}", typeof itemData[1] == 'string' ? quoteForPowerShell(itemData[1]) : '') }; case "KillProcess/Windows": return { processor: 'ps', invalidatesCommand: 'GetProcesses', commandKeyIndices: [0], commandKey: itemData[0], commandText: SC.util.formatString("Stop-Process {0} -ErrorAction SilentlyContinue -Force", typeof itemData[0] == 'string' ? quoteForPowerShell(itemData[0]) : '') }; case "UninstallSoftware/Windows": return { processor: 'ps', invalidatesCommand: 'GetSoftware', commandKeyIndices: [0], commandKey: itemData[0], commandText: itemData[4].toLowerCase().startsWith("msiexec") ? SC.util.formatString(parseMsiExecuteCommand(itemData[4], itemData[0])) : SC.util.formatString("echo '{0}'", itemData[1]) }; case "StopService/Windows": return { processor: 'ps', invalidatesCommand: 'GetServices', commandKeyIndices: [0], commandKey: itemData[0], commandText: SC.util.formatString("Stop-Service {0}", typeof itemData[0] == 'string' ? quoteForPowerShell(itemData[0]) : '') }; case "StartService/Windows": return { processor: 'ps', invalidatesCommand: 'GetServices', commandKeyIndices: [0], commandKey: itemData[0], commandText: SC.util.formatString("Start-Service {0}", typeof itemData[0] == 'string' ? quoteForPowerShell(itemData[0]) : '') }; case "RestartService/Windows": return { processor: 'ps', invalidatesCommand: 'GetServices', commandKeyIndices: [0], commandKey: itemData[0], commandText: SC.util.formatString("Restart-Service {0}", typeof itemData[0] == 'string' ? quoteForPowerShell(itemData[0]) : '') }; case "InstallUpdate/Windows": return { processor: 'ps', invalidatesCommand: 'GetUpdates', commandKeyIndices: [0], commandKey: itemData[0], commandText: "$session = New-Object -ComObject \"Microsoft.Update.Session\"" + "\n" + "$searcher = $session.CreateUpdateSearcher()" + "\n" + SC.util.formatString("$search = \"(UpdateID = {0})\"", typeof itemData[0] == 'string' ? quoteForPowerShell(itemData[0]) : '') + "\n" + "$updateResult = $searcher.Search($search)" + "\n" + "$downloader = $session.CreateUpdateDownloader()" + "\n" + "$installer = $session.CreateUpdateInstaller()" + "\n" + "$downloader.Updates = $updateResult.Updates" + "\n" + "$installer.Updates = $updateResult.Updates" + "\n" + "$result = ''" + "\n" + "Try{ $result = $downloader.Download() } Catch{ If($_ -match \"HRESULT: 0x80240044\") { $result = \"Insufficient permissions. Could not install updates under this identity.\" }}" + "\n" + "Try{ $result = $installer.Install() } Catch{ If($_ -match \"HRESULT: 0x80240044\") { $result = \"Insufficient permissions. Could not install updates under this identity.\" }}" + "\n" + "$result" }; case "RemoveAdmin/Windows": return { processor: 'ps', invalidatesCommand: 'GetUsers', commandKeyIndices: [0], commandKey: itemData[0], commandText: SC.util.formatString("Remove-LocalGroupMember -Group \"Administrators\" -Member {0}", quoteForPowerShell(itemData[0])) } case "StopService/Linux": return { processor: 'sh', invalidatesCommand: 'GetServices', commandKeyIndices: [0], commandKey: itemData[0], commandText: SC.util.formatString("/etc/init.d/{0} stop", itemData[0]) }; case "StartService/Linux": return { processor: 'sh', invalidatesCommand: 'GetServices', commandKeyIndices: [0], commandKey: itemData[0], commandText: SC.util.formatString("/etc/init.d/{0} start", itemData[0]) }; case "RestartService/Linux": return { processor: 'sh', invalidatesCommand: 'GetServices', commandKeyIndices: [0], commandKey: itemData[0], commandText: SC.util.formatString("/etc/init.d/{0} restart", itemData[0]) }; case "UninstallSoftware/Linux": return { processor: 'sh', invalidatesCommand: 'GetSoftware', commandKeyIndices: [0], commandKey: itemData[0], commandText: getCommandTextForLinuxDistributionBasedExecution(SC.util.formatString("rpm --erase {0}", itemData[0]), SC.util.formatString("dpkg --remove {0}", itemData[0])) }; case "StartService/OSX": case "RestartService/OSX": return { processor: 'sh', invalidatesCommand: 'GetServices', commandKeyIndices: [1, 0], commandKey: '' + itemData[1] + itemData[0], commandText: SC.util.formatString("launchctl kickstart " + (remoteCommandName == "RestartService" ? "-k " : "") + "{0}/{1}", itemData[1] == "system" ? "system" : "gui/$(stat -f '%u' /dev/console | grep -vx 0)", itemData[0]) }; default: throw "unhandled commandName/osType combination"; } } });</script> <script>SC.extension.addInitializeProc('6fadbbb8-9540-4612-8504-937c5083bca7', function (extensionContext) { var securityToolkitExtensionId = extensionContext.baseUrl.split('/').slice(-2)[0]; var securityToolkitHelpLink = 'https://docs.connectwise.com/ConnectWise_Control_Documentation/Supported_extensions/Administration/Security_Toolkit'; SC.event.addGlobalHandler(SC.event.QueryCommandButtonState, function (eventArgs) { if (eventArgs.commandName == 'EditExtensionSettings') if (eventArgs.commandContext.extensionInfo.ExtensionID == securityToolkitExtensionId && eventArgs.commandElement._commandName == "EditExtensionSettings") eventArgs.target.parentElement.appendChild($a({ _commandName: 'ShowHelpLink_' + securityToolkitExtensionId, _textResource: 'SecurityToolkit.ShowHelpLink.ButtonText' })); }); SC.event.addGlobalHandler(SC.event.ExecuteCommand, function (eventArgs) { if (eventArgs.commandName == 'ShowHelpLink_' + securityToolkitExtensionId) window.open(securityToolkitHelpLink, '_blank'); }); SC.event.addGlobalHandler(SC.event.PreRender, function (eventArgs) { if (SC.context.pageType === 'AdministrationPage' || (SC.context.pageType === 'HostPage' && SC.context.canAdminister === true)) SC.util.includeStyleSheet(extensionContext.baseUrl + 'SecurityToolkit.css'); }); SC.event.addGlobalHandler(SC.event.QueryCommandButtons, function (eventArgs) { switch (eventArgs.area) { case 'ExtrasPopoutPanel': if (SC.context.pageType === 'AdministrationPage' || (SC.context.pageType === 'HostPage' && SC.context.canAdminister === true)) eventArgs.buttonDefinitions.push( { commandName: 'RemoveQueuedCommands', text: SC.res['SecurityToolkit.ExtrasPanel.RemoveQueuedCommands.Text'] } ); break; } }); SC.event.addGlobalHandler(SC.event.ExecuteCommand, function (eventArgs) { switch (eventArgs.commandName) { case 'RemoveQueuedCommands': removeQueuedCommands(); break; } }); var removeQueuedCommands = function () { SC.dialog.showConfirmationDialog( 'RemoveQueuedCommands', SC.res['SecurityToolkit.RemoveCommandsActionPanel.Title'], $p({ innerHTML: SC.res['SecurityToolkit.RemoveCommandsActionPanel.Text'] }), SC.res['SecurityToolkit.RemoveCommandsActionPanel.ButtonText'], function (onSuccess, onFailure) { SC.service.RemoveAllQueuedCommands( function () { onSuccess(); SC.pagedata.notifyDirty(); }, onFailure ); } ); } });</script> <title> MM Tech Doctor Remote support </title></head> <body> <div class="HiddenPanel"></div> <script> SC.ui.setVisible(document.body, false); </script> <div class="OuterPanel"> <div class="HeaderPanel"></div> <div class="NavigationPanel ArrowNavigation" tabindex="10"></div> <div class="MainPanel"> <div class="ContentPanel"> <div> <div class="WelcomePanel"></div> <div class="ActionPanel"></div> </div> <div class="InfoPanel"></div> </div> </div> </div> <script> SC.context.scriptBaseUrl = SC.util.getBaseUrl($('defaultScript').src); </script> <script> SC.event.addGlobalHandler(SC.event.ExecuteCommand, function (eventArgs) { var session = null; var hostAccessToken = null; switch (eventArgs.commandName) { case 'JoinBySessionID': session = window.getSessionInfo().Sessions.filter(function (s) { return s.SessionID == eventArgs.commandArgument; })[0]; break; case 'JoinByTag': var taggedSessionInfo = window.getTaggedSessionInfo(eventArgs.commandArgument); hostAccessToken = taggedSessionInfo.HostAccessToken; session = window.getSessionInfo().Sessions.filter(function (s) { return s.SessionID == taggedSessionInfo.SessionID || (taggedSessionInfo.Code && s.Code.toLowerCase() == taggedSessionInfo.Code.toLowerCase()); })[0]; break; } // older IE only allows launching urls on actual clicks and this could be sent by a keystroke if (session && (SC.command.doesClickDispatch(eventArgs.commandElement) || !SC.util.isCapable(SC.util.Caps.InternetExplorer, null, { major: 11 }))) { SC.launch.startJoinSession( { session: session, hostAccessToken: hostAccessToken, processType: hostAccessToken ? SC.types.ProcessType.Host : SC.types.ProcessType.Guest }, function (joinInfo, _, onSuccess, onFailure) { onSuccess( SC.util.getClientLaunchParameters( joinInfo.session.SessionID, joinInfo.session.SessionType, joinInfo.session.Name, joinInfo.fieldMap.participantName.value, null, joinInfo.hostAccessToken, joinInfo.processType ) ); } ); } }); SC.event.addGlobalHandler(SC.event.QueryJoinInfo, function (eventArgs) { if (eventArgs.session) { eventArgs.shouldShowPrompt = SC.util.getSessionTypeBooleanResource('JoinPanel.{0}PromptVisible', eventArgs.session.SessionType); eventArgs.promptText = SC.util.getSessionTypeResource('JoinPanel.{0}PromptMessage', eventArgs.session.SessionType); eventArgs.buttonText = SC.util.getSessionTypeResource('JoinPanel.{0}PromptButtonText', eventArgs.session.SessionType); eventArgs.fieldMap.participantName = { labelText: SC.util.getSessionTypeResource('JoinPanel.{0}ParticipantNameLabelText', eventArgs.session.SessionType), value: '', visible: SC.util.getSessionTypeBooleanResource('JoinPanel.{0}PromptParticipantNameVisible', eventArgs.session.SessionType), }; } }); SC.event.addGlobalHandler(SC.event.QueryParticipantJoinedCount, function (eventArgs) { var sessionInfo = window.getSessionInfo(); var session = sessionInfo.Sessions.find(function (s) { return s.SessionID === eventArgs.clientLaunchParameters.s; }); if (session !== undefined) eventArgs.participantJoinedCount = session.ActiveConnections.filter(function (ac) { if (eventArgs.clientLaunchParameters.n) return ac.ProcessType == SC.types.ProcessType.Host; return ac.ProcessType == SC.types.ProcessType.Guest && ac.ParticipantName == eventArgs.clientLaunchParameters.r; }).length; }); SC.event.addGlobalHandler(SC.event.QueryPanels, function (eventArgs) { switch (eventArgs.area) { case 'GuestActionPanel': eventArgs.panelDefinitions.push({ initProc: function (container) { SC.ui.setContents(container, $div({ className: 'Loading' })); }, isVisibleProc: function (pass, previousPassVisibleCount, sessionInfo) { return pass == 1 && sessionInfo == null; } }); eventArgs.panelDefinitions.push({ initProc: function (container) { SC.ui.setContents(container, [ $a({ _commandName: 'JoinByTag', _commandArgument: 'DefaultSession', className: 'GoLink Large', _attributeMap: { 'aria-label': SC.res['GuestActionPanel.ButtonDescription'] } }), $h2({ _htmlResource: 'GuestActionPanel.InvitationSession.Heading' }), $p({ _htmlResource: 'GuestActionPanel.InvitationSession.Message' }), ]); }, isVisibleProc: function (pass, previousPassVisibleCount, sessionInfo) { return pass == 3 && previousPassVisibleCount == 0 && sessionInfo != null && sessionInfo.Sessions.find(function (s) { return s.SessionID == window.getTaggedSessionInfo('DefaultSession').SessionID; }); } }); eventArgs.panelDefinitions.push({ initProc: function (container) { SC.ui.setContents(container, [ $h2({ _htmlResource: 'GuestActionPanel.CodeSession.Heading' }), $p({ _htmlResource: 'GuestActionPanel.CodeSession.Message' }), $p({ className: 'GuestActionBar' }, [ SC.ui.createSearchTextBox({ _commandName: 'JoinByTag', _commandArgument: 'DefaultCode', value: window.getTaggedSessionInfo('DefaultCode').Code || '' }, function (eventArgs) { var sessionCode = SC.util.getTrimmedOrNull(SC.event.getElement(eventArgs).value); window.setTaggedSessionInfo('DefaultCode', { Code: sessionCode }); }), $a({ _commandName: 'JoinByTag', _commandArgument: 'DefaultCode', className: 'GoLink Medium', _attributeMap: { 'aria-label': SC.res['GuestActionPanel.ButtonDescription'] } }), ]), ]); }, isVisibleProc: function (pass, previousPassVisibleCount, sessionInfo) { return pass == 5 && previousPassVisibleCount == 0 && sessionInfo != null && sessionInfo.DoNonPublicCodeSessionsExist; }, refreshProc: function (container, sessionInfo, wasMadeVisible) { var taggedSessionInfo = window.getTaggedSessionInfo('DefaultCode'); SC.ui.setDisabled( SC.ui.findDescendentByTag(container, 'A'), !sessionInfo.Sessions.find(function (s) { return taggedSessionInfo.Code && s.Code.toLowerCase() == taggedSessionInfo.Code.toLowerCase(); }) ); if (wasMadeVisible) SC.ui.findDescendentByTag(container, 'INPUT').focus(); } }); eventArgs.panelDefinitions.push({ initProc: function (container) { SC.ui.setContents(container, [ $h2({ _htmlResource: 'GuestActionPanel.PublicSession.Heading' }), $p({ _htmlResource: 'GuestActionPanel.PublicSession.Message' }), $p({ className: 'GuestActionBar' }, [ $select(), $a({ _commandName: 'JoinBySessionID', className: 'GoLink Medium', _attributeMap: { 'aria-label': SC.res['GuestActionPanel.ButtonDescription'] } }), ]), ]); SC.event.addHandler(SC.ui.findDescendentByTag(container, 'SELECT'), 'change', function (eventArgs) { var selectBox = SC.event.getElement(eventArgs); SC.ui.findDescendentByTag(container, 'A')._commandArgument = selectBox.options[selectBox.selectedIndex].value; }); }, isVisibleProc: function (pass, previousPassVisibleCount, sessionInfo) { return pass == 5 && previousPassVisibleCount == 0 && sessionInfo != null && sessionInfo.Sessions.filter(function (s) { return s.IsPublic; }).length > 0; }, refreshProc: function (container, sessionInfo, wasMadeVisible) { var selectBox = SC.ui.findDescendentByTag(container, 'SELECT'); var link = SC.ui.findDescendentByTag(container, 'A'); SC.ui.setContents(selectBox, sessionInfo.Sessions.filter(function (s) { return s.IsPublic; }).map(function (s) { return $option({ value: s.SessionID }, s.Name); }) ); var optionIndex = Array.prototype.findIndex.call(selectBox.options, function (o) { return o.value == link._commandArgument; }); if (optionIndex != -1) selectBox.selectedIndex = optionIndex; else link._commandArgument = selectBox.options[selectBox.selectedIndex].value; } }); eventArgs.panelDefinitions.push({ initProc: function (container) { SC.ui.setContents(container, [ $h2({ _htmlResource: 'GuestActionPanel.NoAvailableSessions.Heading' }), $p({ _htmlResource: 'GuestActionPanel.NoAvailableSessions.Message' }), ]); }, isVisibleProc: function (pass, previousPassVisibleCount, sessionInfo) { return pass == 8 && previousPassVisibleCount == 0; } }); break; } }); SC.event.addGlobalHandler(SC.event.QueryLiveData, function (eventArgs) { var getTaggedValuesFunc = function (propertyName) { return Object.keys(window._taggedSessionInfos) .map(function (key) { return window._taggedSessionInfos[key]; }) .filter(function (_) { return _[propertyName]; }) .map(function (_) { return _[propertyName]; }); } eventArgs.requestInfoMap['GuestSessionInfo'] = { sessionCodes: getTaggedValuesFunc('Code'), sessionIDs: getTaggedValuesFunc('SessionID'), }; }); SC.event.addGlobalHandler(SC.event.PreRender, function () { window._taggedSessionInfos = {}; SC.css.ensureClass(document.documentElement, 'ShowMenu', false); var queryStringMap = SC.util.parseQueryString(window.location.search); window.setTaggedSessionInfo('DefaultCode', { Code: queryStringMap.Code }); window.setTaggedSessionInfo('DefaultSession', { SessionID: queryStringMap.Session, HostAccessToken: queryStringMap.HostAccessToken }); var welcomePanel = $('.WelcomePanel'); var actionPanel = $('.ActionPanel'); SC.ui.setVisible(welcomePanel, SC.util.getBooleanResource('GuestWelcomePanel.Visible')); SC.ui.setContents(welcomePanel, [ $h2({ _htmlResource: 'GuestWelcomePanel.Heading' }), $p({ _htmlResource: 'GuestWelcomePanel.Message' }), ]); SC.panellist.queryAndInitializePanels(actionPanel); SC.panellist.refreshPanels(actionPanel, null); }); SC.event.addGlobalHandler(SC.event.LiveDataRefreshed, function () { SC.panellist.refreshPanels($('.ActionPanel'), window.getSessionInfo()); if (!window._hasJoinedDefault && !SC.util.isCapable(SC.util.Caps.InternetExplorer, null, { major: 11 })) { SC.command.dispatchExecuteCommand(window.document.body, window.document.body, window.document.body, 'JoinByTag', 'DefaultSession'); window._hasJoinedDefault = true; } }); </script> <script> SC.event.addGlobalHandler(SC.event.QueryCommandButtons, function (eventArgs) { switch (eventArgs.area) { case 'TrayIconPanel': eventArgs.buttonDefinitions.push({ commandName: 'ActionCenter', imageUrl: 'Images/ActionCenter.svg' }); if (SC.context.isUserAdministrator) eventArgs.buttonDefinitions.push({ commandName: 'Navigate', commandArgument: 'Administration', imageUrl: 'Images/NavigationAdministration.svg' }); eventArgs.buttonDefinitions.push( { commandName: 'Extras', imageUrl: 'Images/Extras.svg' }, { commandName: 'Applications', imageUrl: 'Images/Applications.svg' } ); break; case 'ExtrasNavigationPopoutPanel': eventArgs.buttonDefinitions.push( { commandName: 'NavigateExtensionBrowser' } ); break; case 'ToolsPanel': eventArgs.buttonDefinitions.push( { commandName: 'Extras', imageUrl: 'Images/Extras.svg' }, { commandName: 'Login' } ); break; case 'UserPopoutPanel': eventArgs.buttonDefinitions.push( { commandName: 'NavigateControlPanel' }, { commandName: 'ChangePassword' }, { commandName: 'Logout' } ); break; case 'UserHelpPopoutPanel': if (SC.context.pageType !== 'GuestPage' && SC.context.pageType != 'LoginPage') { eventArgs.buttonDefinitions.push({ commandName: 'GiveFeedback' }); for (var i = 1; ; i++) { var resourceValue = SC.res['HelpPanel.Link' + i + '.Text']; if (resourceValue === undefined || resourceValue === '') break; var url = SC.util.sanitizeUrl(SC.res['HelpPanel.Link' + i + '.Url']); eventArgs.buttonDefinitions.push({ commandName: 'NavigateHelpLink', commandArgument: url, text: resourceValue, title: url }); } } break; } }); SC.event.addGlobalHandler(SC.event.QueryCommandButtonState, function (eventArgs) { switch (eventArgs.commandName) { case 'User': case 'ActionCenter': eventArgs.isVisible = SC.context.isUserAuthenticated; break; case 'Login': eventArgs.isVisible = SC.context.pageType != 'SetupWizardPage' && !SC.context.isUserAuthenticated && !SC.util.isCapable(SC.util.Caps.InternetExplorer, null, { major: 12 }); // Login page doesn't support IE break; case 'NavigateControlPanel': eventArgs.isVisible = !!SC.context.controlPanelUrl; break; case 'ChangePassword': eventArgs.isVisible = SC.context.canChangePassword; break; case 'Extras': eventArgs.isVisible = SC.popout.computePopoutCommandsVisible(eventArgs, ['', 'Navigation']); break; case 'Applications': case 'Help': eventArgs.isVisible = SC.popout.computePopoutCommandsVisible(eventArgs); break; case 'NavigateExtensionBrowser': eventArgs.isVisible = SC.context.isUserAdministrator; break; } }); SC.event.addGlobalHandler(SC.event.ExecuteCommand, function (eventArgs) { switch (eventArgs.commandName) { case 'Extras': SC.popout.showPanelFromCommand(eventArgs, null, { subAreas: ['', 'Navigation'] }); break; case 'Applications': SC.popout.showPanelFromCommand(eventArgs); break; case 'ActionCenter': SC.popout.showPanelFromCommand(eventArgs, null, { buildProc: function (popoutPanel) { var actionCenterInfo = SC.livedata.getResponseInfo(SC.livedata.ActionCenterInfo); SC.ui.setContents(popoutPanel, $div({ className: 'ActionCenterPanel' }, [ $h2({ _textResource: 'ActionCenterPanel.Text' }), $ul({ className: 'List', _visible: SC.util.any(actionCenterInfo.ActionItems) }, (actionCenterInfo.ActionItems || []) .map(function (it) { var parsedEventData = SC.util.parseEventData(it.Data); return $li({ _eventHandlerMap: { click: function () { window.location.href = SC.nav.getHostUrl({ sessionType: it.SessionType, sessionID: it.SessionID, tabName: SC.nav.getHostTabName(it.EventType), tabContext: it.EventID }); }, } }, [ $img({ src: 'Images/Notification' + SC.util.getEnumValueName(SC.types.SessionEventType, it.EventType) + '.svg' }), $h3({ className: 'Type' }, SC.res['SessionEvent.' + SC.util.getEnumValueName(SC.types.SessionEventType, it.EventType) + '.Title']), $p({ className: 'Name', title: it.Name }, it.Name), $p({ className: 'DataContent', title: parsedEventData.content }, parsedEventData.content), $p({ className: 'Time' }, SC.util.formatDateTime(it.Time, { includeRelativeDate: true })), ]) }) ), $div({ className: 'EmptyPanel', _visible: !SC.util.any(actionCenterInfo.ActionItems) }, [ $p($img({ src: 'images/EmptyActionCenter.svg' })), $h4({ _textResource: 'ActionCenterPanel.EmptyHeader' }), $p({ _textResource: 'ActionCenterPanel.EmptyText' }), ]), ])); }, }); break; case 'Login': SC.util.sendToLogin(SC.types.LoginReason.None, false); break; case 'Logout': SC.util.sendToLogin(SC.types.LoginReason.Logout, false); break; case 'User': SC.popout.showPanelFromCommand(eventArgs, null, { subAreas: ['Help', ''] }); break; case 'NavigateControlPanel': window.open(SC.util.sanitizeUrl(SC.context.controlPanelUrl)); break; case 'ChangePassword': var params = {}; params[SC.context.loginUserNameParameterName] = eventArgs.commandArgument; window.location.href = SC.context.changePasswordPageUrl + SC.util.getQueryString(params); break; case 'NavigateHelpLink': window.open(eventArgs.commandArgument); break; case 'ToggleMenu': SC.css.toggleClass(document.documentElement, 'ShowMenu'); break; case 'GiveFeedback': SC.dialog.showModalButtonDialog( 'GiveFeedback', SC.res['Command.GiveFeedback.Text'], SC.res['Command.GiveFeedback.ButtonText'], 'Default', function (container) { SC.ui.setContents(container, [ $div({ _textResource: 'GiveFeedbackPanel.ReviewLabelText' }), $div({ className: 'RatingSelectionPanel' }, ['Good', 'Neutral', 'Bad'].map(function (rating) { return $span( $label({ className: rating }, [ $input({ type: 'radio', name: 'rating', value: rating.toLowerCase() }), $div({ className: 'RadioImage' }), $span({ _textResource: 'GiveFeedbackPanel.' + rating + 'RatingLabelText' }), ]) ); }) ), $div([ $label({ _textResource: 'GiveFeedbackPanel.EmailLabelText' }, [ $input({ type: 'email', id: 'email' }), ]), ]), $div([ $label({ _textResource: 'GiveFeedbackPanel.CommentsLabelText' }, [ SC.ui.createTextBox({ id: 'commentsBox' }, true), ]), ]), ]); }, function (eventArgs) { SC.service.SendFeedback( Array.prototype.map.call(document.querySelectorAll('input[name=rating]:checked'), function (e) { return e.value; })[0], $('commentsBox').value, $('email').value, function () { SC.dialog.showModalMessageBox( SC.res['GiveFeedbackPanel.SuccessHeading'], SC.res['GiveFeedbackPanel.SuccessMessage'] ); } ); } ); break; case 'ManageToolbox': SC.toolbox.showToolboxDialog(eventArgs.commandName, eventArgs.commandArgument); break; case 'Navigate': window.location.href = eventArgs.commandArgument; break; case 'NavigateExtensionBrowser': window.location.href = SC.context.administrationPageUrl + '?Tab=Extensions#ShowExtensionBrowser'; break; } }); SC.event.addGlobalHandler(SC.event.QueryNavigationLinks, function (eventArgs) { Array.prototype.push.apply(eventArgs.navigationLinks, SC.context.sessionTypeInfos.map(function (_) { return { href: SC.context.scriptBaseUrl + SC.context.hostPageUrl + '#' + SC.util.getEnumValueName(SC.types.SessionType, _.sessionType), text: SC.util.getSessionTypeResource('NavigationPanel.{0}LinkText', _.sessionType), imageUrl: SC.util.formatString('Images/Navigation{0}.svg', SC.util.getEnumValueName(SC.types.SessionType, _.sessionType)), sessionType: _.sessionType, } })); }); SC.event.addGlobalHandler(SC.event.QueryLiveData, function (eventArgs) { if (SC.context.isUserAuthenticated) SC.livedata.setRequestInfo(eventArgs, SC.livedata.ActionCenterInfo); }); SC.event.addGlobalHandler(SC.event.LiveDataRefreshed, function () { SC.css.ensureClass($('.NavigationPanel .TrayIconPanel .ActionCenter'), 'NonEmpty', SC.util.any(SC.livedata.getResponseInfo(SC.livedata.ActionCenterInfo).ActionItems)); }); SC.event.addGlobalHandler('keydown', function (eventArgs) { if (SC.event.doesKeyEventIndicateTextEntryOrArrowKeyNavigation(eventArgs) && (!document.activeElement || SC.ui.isDefinitelyNotTextEntryElement(document.activeElement))) { var arrowKeyInfo = SC.event.getArrowKeyInfo(eventArgs); if (arrowKeyInfo && document.activeElement && SC.css.containsClass(document.activeElement, 'ArrowNavigation')) { eventArgs.preventDefault(); SC.ui.setHiddenFocusAndClearOthers(); var targetPreviousOrNext = arrowKeyInfo.isLeft || arrowKeyInfo.isUp; SC.event.dispatchEvent(document.activeElement, SC.event.KeyNavigation, { currentActiveElement: document.activeElement, currentSelectedElement: SC.ui.findDescendantBreadthFirst(document.activeElement, function (_) { return SC.ui.isSelected(_); }, !targetPreviousOrNext), targetPreviousOrNext: targetPreviousOrNext, arrowKeyInfo: arrowKeyInfo, hasShift: eventArgs.shiftKey, }); } else { var queryTextEntryElementArgs = SC.event.dispatchGlobalEvent(SC.event.QueryTextEntryElement, { textEntryElement: null, }); if (queryTextEntryElementArgs.textEntryElement) { if (!SC.event.doesKeyEventIndicateTextEntryNavigation(eventArgs)) queryTextEntryElementArgs.textEntryElement.value = ''; queryTextEntryElementArgs.textEntryElement.focus(); } } } }); SC.event.addGlobalHandler(SC.event.KeyNavigation, function (eventArgs) { // default handling for key navigation var elementToNavigateTo; if (eventArgs.currentSelectedElement) { elementToNavigateTo = SC.ui.getPreviousOrNextElementSibling(eventArgs.currentSelectedElement, eventArgs.targetPreviousOrNext) || eventArgs.currentSelectedElement; while (SC.util.isNullOrEmpty(elementToNavigateTo._commandName) && SC.ui.getPreviousOrNextElementSibling(elementToNavigateTo, eventArgs.targetPreviousOrNext)) { elementToNavigateTo = SC.ui.getPreviousOrNextElementSibling(elementToNavigateTo, eventArgs.targetPreviousOrNext); } } else { elementToNavigateTo = SC.ui.findDescendantBreadthFirst(eventArgs.currentActiveElement, function (_) { return !SC.util.isNullOrEmpty(_._commandName); }); // this can still be empty } SC.util.tryNavigateToElementUsingCommand(elementToNavigateTo, eventArgs.targetPreviousOrNext, eventArgs.hasShift); }); SC.event.addGlobalHandler(SC.event.PreRender, function () { var resetInactivityProc = function () { window._lastNotifyActivityTime = new Date().getTime(); if (SC.context.isUserAuthenticated && SC.context.loginAfterInactivityMilliseconds != 0) { if (window._loginAfterInactivityTimer) window.clearTimeout(window._loginAfterInactivityTimer); window._loginAfterInactivityTimer = window.setTimeout(function () { SC.util.sendToLogin(SC.types.LoginReason.IdleTooLong, true); }, Math.min(SC.context.loginAfterInactivityMilliseconds, 2147483647)); //interval stored as 32-bit signed int } }; SC.context.prehandleServiceFailureProc = function (error) { if (error.statusCode != 403) return false; SC.util.sendToLogin(SC.types.LoginReason.PermissionsInsufficient, true); } SC.context.unhandledServiceFailureProc = function (error) { SC.dialog.showModalErrorBox(error.detail || error.message); } resetInactivityProc(); SC.ui.initializeWindowActivityTracking(function () { if (new Date().getTime() - window._lastNotifyActivityTime > SC.context.notifyActivityFrequencyMilliseconds) { resetInactivityProc(); SC.service.NotifyActivity(); } }); var parameterlessUrl = SC.util.getParameterlessUrl(window.location.href); var createNavigationLinkFunc = function (_) { return $div({ _commandName: 'Navigate', _commandArgument: _.href, _selected: _.href == parameterlessUrl }, [ $img({ src: _.imageUrl }), $span(_.text), ]); }; SC.ui.setContents($('.HeaderPanel'), [ $a({ href: SC.context.guestPageUrl, className: 'LogoIconLink' }), $a({ _commandName: 'ToggleMenu', className: 'ShowMenuButton' }, ''), $h1({ className: 'LogoPanel' }), $div({ className: 'CommandPanel' }), ]); SC.command.queryAndAddCommandButtons($('.HeaderPanel .CommandPanel'), 'ToolsPanel'); SC.command.updateCommandButtonsState($('.HeaderPanel .CommandPanel')); var queryNavigationLinksEventArgs = SC.event.dispatchGlobalEvent(SC.event.QueryNavigationLinks, { navigationLinks: [] }) SC.ui.setContents($('.NavigationPanel'), [ queryNavigationLinksEventArgs.navigationLinks.map(createNavigationLinkFunc), $div({ className: 'FlexSpacer' }), $div({ className: 'TrayPanelContainer' }, [ $div({ className: 'TrayIconPanel' }), $div({ className: 'UserMenuButton', _commandName: 'User' }, $span(SC.context.userDisplayName == null ? '' : SC.context.userDisplayName.toUpperCase()[0]), $span(SC.context.userDisplayName) ), ]), ]); SC.command.queryAndAddCommandButtons($('.NavigationPanel .TrayIconPanel'), 'TrayIconPanel', null, { descriptionRenderStyle: SC.command.DescriptionRenderStyle.Tooltip }); SC.command.updateCommandButtonsState($('.NavigationPanel .TrayIconPanel')); var setSelectedFunc = function () { $$('.NavigationPanel > div') .filter(function (_) { return !SC.util.isNullOrEmpty(_._commandArgument); }) .forEach(function (_) { SC.ui.setSelected(_, window.location.href.startsWith(_._commandArgument)); }); }; SC.event.addHandler(window, 'hashchange', setSelectedFunc); setSelectedFunc(); SC.livedata.startLoop(); }); var isTouchEnabled = (typeof document.documentElement.ontouchstart !== 'undefined'); SC.css.ensureClass(document.documentElement, 'TouchEnabled', isTouchEnabled); SC.css.ensureClass(document.documentElement, 'TouchDisabled', !isTouchEnabled); SC.css.ensureClass(document.documentElement, 'UserAuthenticated', SC.context.isUserAuthenticated); SC.css.ensureClass(document.documentElement, 'NativeClient', SC.util.isCapable(SC.util.Caps.NativeClient)); SC.css.ensureClass(document.documentElement, 'HasMasterPanel', $('.MasterPanel')); SC.css.ensureClass(document.documentElement, 'LogoImageVisible', SC.util.getBooleanResource('LogoPanel.ImageVisible')); SC.css.ensureClass(document.documentElement, 'LogoIconVisible', SC.util.getBooleanResource('LogoPanel.IconVisible')); SC.css.ensureClass(document.documentElement, 'LogoHeadingVisible', SC.util.getBooleanResource('LogoPanel.HeadingVisible')); SC.css.ensureClass(document.documentElement, 'AnimationReduced', SC.util.getBooleanResource('Page.AnimationReduced')); SC.css.ensureClass(document.documentElement, SC.context.pageType, true); SC.extension.initializeExtensions(); SC.event.dispatchGlobalEvent(SC.event.PreRender); SC.util.recordLifeCycleEvent(SC.event.PreRender); SC.ui.setVisible(document.body, true); SC.event.dispatchGlobalEvent(SC.event.PostRender); SC.util.recordLifeCycleEvent(SC.event.PostRender); $$('*[tabIndex]').forEach(function (_) { SC.event.addHandler(_, 'mousedown', function () { SC.ui.setHiddenFocusAndClearOthers(_); }); }); if (SC.context.focusedControlID) $(SC.context.focusedControlID).focus(); else if (document.activeElement == document.body) { $('.NavigationPanel').focus(); SC.ui.setHiddenFocusAndClearOthers($('.NavigationPanel')); } </script> </body> </html>