function Invoke-TasksCompleted { param($Context) Write-LogHybrid "All UI-selected tasks processed" Info UI -LogToEvent Send-Text $Context "Tasks completion acknowledged." } function Dispatch-Request { param($Context) if ($null -eq $Context -or $null -eq $Context.Request -or $null -eq $Context.Request.Url) { return } try { $path = $Context.Request.Url.AbsolutePath.TrimStart('/') switch -Regex ($path) { '^$' { $html = Get-UIHtml -Page 'onboard' Send-HTML $Context $html return } '^samy\.js$' { Send-RemoteAsset -Context $Context -Url $Script:SamyJsUrl -ContentType 'application/javascript; charset=utf-8' return } '^samy\.css$' { Send-RemoteAsset -Context $Context -Url $Script:SamyCssUrl -ContentType 'text/css; charset=utf-8' return } '^SVS_logo\.svg$' { Send-RemoteAsset -Context $Context -Url $Script:SamyTopLogoUrl -ContentType 'image/svg+xml' return } '^SAMY\.png$' { Send-RemoteAsset -Context $Context -Url $Script:SamyBgLogoUrl -ContentType 'image/png' return } '^SVS_Favicon\.ico$' { Send-RemoteAsset -Context $Context -Url $Script:SamyFaviconUrl -ContentType 'image/x-icon' return } } if ($path -eq 'quit') { Write-LogHybrid "Shutdown requested" "Info" "Server" -LogToEvent Send-Text $Context "Server shutting down." $Global:Listener.Stop() return } if ($Context.Request.HttpMethod -eq 'POST' -and $path -eq 'tasksCompleted') { Invoke-TasksCompleted $Context; return } if ($Context.Request.HttpMethod -eq 'POST' -and $path -eq 'getpw') { Invoke-FetchSites $Context; return } if ($Context.Request.HttpMethod -eq 'POST' -and $path -eq 'renameComputer') { Invoke-RenameComputer $Context; return } if ($Context.Request.HttpMethod -eq 'POST' -and $path -eq 'getprinters') { Invoke-GetPrinters $Context; return } if ($Context.Request.HttpMethod -eq 'POST' -and $path -eq 'installprinters'){ Invoke-InstallPrinters $Context; return } if ($path -in @('onboard', 'offboard', 'devices')) { $html = Get-UIHtml -Page $path Send-HTML $Context $html return } $task = $Global:SamyTasks | Where-Object Name -EQ $path | Select-Object -First 1 if ($task) { $fn = Get-TaskHandlerName -Task $task if ([string]::IsNullOrWhiteSpace($fn)) { $Context.Response.StatusCode = 500 Send-Text $Context "Task '$($task.Label)' is missing a handler (HandlerFn/Handler/Fn/Name)." return } $cmd = Get-Command -Name $fn -ErrorAction SilentlyContinue if (-not $cmd) { $Context.Response.StatusCode = 500 Send-Text $Context "Handler not found: $fn" return } if ($cmd.Parameters.ContainsKey('Context')) { & $fn -Context $Context } else { & $fn } return } $Context.Response.StatusCode = 404 Send-Text $Context '404 - Not Found' } catch { # Always return something so clients don't hang try { $Context.Response.StatusCode = 500 $pos = if ($_.InvocationInfo) { $_.InvocationInfo.PositionMessage } else { "" } $stk = if ($_.ScriptStackTrace) { $_.ScriptStackTrace } else { "" } $msg = "Dispatch error: $($_.Exception.Message)`n$pos`n$stk" $bytes = [Text.Encoding]::UTF8.GetBytes($msg) $Context.Response.ContentType = 'text/plain; charset=utf-8' $Context.Response.ContentLength64 = $bytes.Length $Context.Response.OutputStream.Write($bytes, 0, $bytes.Length) } catch { } } finally { try { $Context.Response.OutputStream.Close() } catch { } try { $Context.Response.Close() } catch { } } }