diff --git a/ShiftOS.Server/Program.cs b/ShiftOS.Server/Program.cs index 3e0455a..7204127 100644 --- a/ShiftOS.Server/Program.cs +++ b/ShiftOS.Server/Program.cs @@ -326,16 +326,21 @@ Contents: } break; case "trm_invcmd": + Console.WriteLine("Before arg check"); + args = JsonConvert.DeserializeObject>(msg.Contents); if(args["guid"] != null && args["command"] != null) { + Console.WriteLine("arg check finished"); string cmd = args["command"] as string; string cGuid = args["guid"] as string; + Console.WriteLine("Before dispatch"); server.DispatchTo(new Guid(cGuid), new NetObject("trminvoke", new ServerMessage { Name = "trm_invokecommand", GUID = "server", Contents = cmd })); + Console.WriteLine("After dispatch"); } break; case "usr_givecp": diff --git a/ShiftOS.WinForms/Applications/Terminal.cs b/ShiftOS.WinForms/Applications/Terminal.cs index 2708e85..133858c 100644 --- a/ShiftOS.WinForms/Applications/Terminal.cs +++ b/ShiftOS.WinForms/Applications/Terminal.cs @@ -253,10 +253,11 @@ namespace ShiftOS.WinForms.Applications if (IsInRemoteSystem == true) { - ServerManager.SendMessage("trm_invcmd", $@"{{ - guid = ""{RemoteGuid}"", - command: ""{text4}"" -}}"); + ServerManager.SendMessage("trm_invcmd", JsonConvert.SerializeObject(new + { + guid = RemoteGuid, + command = text4 + })); } else { diff --git a/ShiftOS_TheReturn/Command.cs b/ShiftOS_TheReturn/Command.cs index 1652a11..85da6ca 100644 --- a/ShiftOS_TheReturn/Command.cs +++ b/ShiftOS_TheReturn/Command.cs @@ -28,39 +28,51 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -namespace ShiftOS.Engine { - public class Command : Attribute { +namespace ShiftOS.Engine +{ + public class Command : Attribute + { public string name; public string description = ""; public string usage = ""; public bool hide = false; - public Command(string name) { + public Command(string name) + { this.name = name; } - public Command(string name, bool hide) { + public Command(string name, bool hide) + { this.name = name; this.hide = hide; } - public Command(string name, string usage, string description) { + public Command(string name, string usage, string description) + { this.name = name; this.description = description; this.usage = usage; } } - public class RequiresUpgradeAttribute : Attribute { + public class RequiresUpgradeAttribute : Attribute + { public string Upgrade { get; set; } - public bool Installed { - get { - if (Upgrade.Contains(";")) { + public bool Installed + { + get + { + if (Upgrade.Contains(";")) + { string[] split = Upgrade.Split(';'); - foreach (var upg in split) { + foreach (var upg in split) + { if (!Shiftorium.UpgradeInstalled(upg)) return false; } return true; - } else { + } + else + { return Shiftorium.UpgradeInstalled(Upgrade); } } @@ -70,30 +82,36 @@ namespace ShiftOS.Engine { /// Marks this Form or Command as dependant on this upgrade. /// /// Upgrade ID - See 'shiftorium.json' in resources for all IDs and their metadata. - public RequiresUpgradeAttribute(string upg) { + public RequiresUpgradeAttribute(string upg) + { Upgrade = upg; } } - public class Namespace : Attribute { + public class Namespace : Attribute + { public string name; public bool hide; - public Namespace(string n) { + public Namespace(string n) + { name = n; } - public Namespace(string n, bool hide) { + public Namespace(string n, bool hide) + { name = n; this.hide = hide; } } [AttributeUsage(AttributeTargets.Method)] - public class CommandObsolete : Attribute { + public class CommandObsolete : Attribute + { public string reason; public string newcommand; public bool warn; - public CommandObsolete(string reason, string newcommand, bool warn) { + public CommandObsolete(string reason, string newcommand, bool warn) + { this.reason = reason; // %n for newcommand this.newcommand = newcommand; this.warn = warn; @@ -101,17 +119,30 @@ namespace ShiftOS.Engine { } [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] - public class RequiresArgument : Attribute { + public class RequiresArgument : Attribute + { public string argument; - public RequiresArgument(string argument) { + public RequiresArgument(string argument) + { this.argument = argument; } - public override object TypeId { - get { + public override object TypeId + { + get + { return this; } } } + + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] + public class RemoteLockAttribute : Attribute + { + /// + /// When used on a terminal command, it will prevent that command from being invoked by a remote user (over MUD terminal forwarding). + /// + public RemoteLockAttribute() { } + } } diff --git a/ShiftOS_TheReturn/Commands.cs b/ShiftOS_TheReturn/Commands.cs index 70486bb..9aae1f6 100644 --- a/ShiftOS_TheReturn/Commands.cs +++ b/ShiftOS_TheReturn/Commands.cs @@ -308,6 +308,7 @@ namespace ShiftOS.Engine [Namespace("sos")] public static class ShiftOSCommands { + [RemoteLock] [Command("shutdown")] public static bool Shutdown() { @@ -540,7 +541,7 @@ shiftorium.buy{{upgrade:""{upg.ID}""}}"); - + [RemoteLock] [Command("list")] public static bool List() { @@ -553,6 +554,7 @@ shiftorium.buy{{upgrade:""{upg.ID}""}}"); return true; } + [RemoteLock] [Command("open")] public static bool Open(Dictionary args) { diff --git a/ShiftOS_TheReturn/TerminalBackend.cs b/ShiftOS_TheReturn/TerminalBackend.cs index de9e179..4edc709 100644 --- a/ShiftOS_TheReturn/TerminalBackend.cs +++ b/ShiftOS_TheReturn/TerminalBackend.cs @@ -66,7 +66,7 @@ namespace ShiftOS.Engine public static string LastCommand = ""; - public static void InvokeCommand(string text) + public static void InvokeCommand(string text, bool isRemote = false) { try { @@ -75,7 +75,7 @@ namespace ShiftOS.Engine var args = GetArgs(ref text); - bool commandWasClient = RunClient(text, args); + bool commandWasClient = RunClient(text, args, isRemote); if (!commandWasClient && !string.IsNullOrWhiteSpace(text)) { @@ -109,7 +109,21 @@ namespace ShiftOS.Engine TerminalRequested?.Invoke(); } - public static bool RunClient(string text, Dictionary args) + public static bool CanRunRemotely(MethodInfo mth, bool isRemote) + { + if (!isRemote) + return true; + + foreach(var attr in mth.GetCustomAttributes(false)) + { + if (attr is RemoteLockAttribute) + return false; + } + + return true; + } + + public static bool RunClient(string text, Dictionary args, bool isRemote = false) { latestCommmand = text; @@ -136,97 +150,105 @@ namespace ShiftOS.Engine { if (Shiftorium.UpgradeAttributesUnlocked(method)) { - foreach (var ma in method.GetCustomAttributes(false)) + if (CanRunRemotely(method, isRemote)) { - if (ma is Command) + foreach (var ma in method.GetCustomAttributes(false)) { - var cmd = ma as Command; - if (text.Split('.')[1] == cmd.name) + if (ma is Command) { - - var attr = method.GetCustomAttribute(); - - if (attr != null) + var cmd = ma as Command; + if (text.Split('.')[1] == cmd.name) { - string newcommand = attr.newcommand; - if (attr.warn) + + var attr = method.GetCustomAttribute(); + + if (attr != null) { - Console.WriteLine(Localization.Parse((newcommand == "" ? "{ERROR}" : "{WARN}") + attr.reason, new Dictionary() { + string newcommand = attr.newcommand; + if (attr.warn) + { + Console.WriteLine(Localization.Parse((newcommand == "" ? "{ERROR}" : "{WARN}") + attr.reason, new Dictionary() { {"%newcommand", newcommand} })); - } - if (newcommand != "") - { - // redo the entire process running newcommand - - return RunClient(newcommand, args); - } - } - - var requiresArgs = method.GetCustomAttributes(); - - bool error = false; - bool providedusage = false; - - foreach (RequiresArgument argument in requiresArgs) - { - if (!args.ContainsKey(argument.argument)) - { - - if (!providedusage) + } + if (newcommand != "") { - string usageparse = "{COMMAND_" + ns.name.ToUpper() + "_" + cmd.name.ToUpper() + "_USAGE}"; - if (usageparse == Localization.Parse(usageparse)) - usageparse = ""; - else - usageparse = Shiftorium.UpgradeInstalled("help_usage") ? Localization.Parse("{ERROR}{USAGE}" + usageparse, new Dictionary() { + // redo the entire process running newcommand + + return RunClient(newcommand, args); + } + } + + var requiresArgs = method.GetCustomAttributes(); + + bool error = false; + bool providedusage = false; + + foreach (RequiresArgument argument in requiresArgs) + { + if (!args.ContainsKey(argument.argument)) + { + + if (!providedusage) + { + string usageparse = "{COMMAND_" + ns.name.ToUpper() + "_" + cmd.name.ToUpper() + "_USAGE}"; + if (usageparse == Localization.Parse(usageparse)) + usageparse = ""; + else + usageparse = Shiftorium.UpgradeInstalled("help_usage") ? Localization.Parse("{ERROR}{USAGE}" + usageparse, new Dictionary() { {"%ns", ns.name}, {"%cmd", cmd.name} }) : ""; - Console.WriteLine(usageparse); + Console.WriteLine(usageparse); - providedusage = true; - } + providedusage = true; + } - if (Shiftorium.UpgradeInstalled("help_usage")) - { - Console.WriteLine(Localization.Parse("{ERROR_ARGUMENT_REQUIRED}", new Dictionary() { + if (Shiftorium.UpgradeInstalled("help_usage")) + { + Console.WriteLine(Localization.Parse("{ERROR_ARGUMENT_REQUIRED}", new Dictionary() { {"%argument", argument.argument} })); - } - else - { - Console.WriteLine(Localization.Parse("{ERROR_ARGUMENT_REQUIRED_NO_USAGE}")); - } + } + else + { + Console.WriteLine(Localization.Parse("{ERROR_ARGUMENT_REQUIRED_NO_USAGE}")); + } - error = true; + error = true; + } } - } - if (error) - { - throw new Exception("{ERROR_COMMAND_WRONG}"); - } + if (error) + { + throw new Exception("{ERROR_COMMAND_WRONG}"); + } - try - { - return (bool)method.Invoke(null, new[] { args }); - } - catch (TargetInvocationException e) - { - Console.WriteLine(Localization.Parse("{ERROR_EXCEPTION_THROWN_IN_METHOD}")); - Console.WriteLine(e.InnerException.Message); - Console.WriteLine(e.InnerException.StackTrace); - return true; - } - catch - { - return (bool)method.Invoke(null, new object[] { }); + try + { + return (bool)method.Invoke(null, new[] { args }); + } + catch (TargetInvocationException e) + { + Console.WriteLine(Localization.Parse("{ERROR_EXCEPTION_THROWN_IN_METHOD}")); + Console.WriteLine(e.InnerException.Message); + Console.WriteLine(e.InnerException.StackTrace); + return true; + } + catch + { + return (bool)method.Invoke(null, new object[] { }); + } } } } } + else + { + Console.WriteLine(text + " cannot be ran in a remote session"); + return true; + } } } } @@ -256,7 +278,7 @@ namespace ShiftOS.Engine IsForwardingConsoleWrites = true; if (TerminalBackend.InStory == false) { - TerminalBackend.InvokeCommand(text3); + TerminalBackend.InvokeCommand(text3, true); } if (TerminalBackend.PrefixEnabled) {