internal void Completed(byte[] rawAssembly = null) { endedAt = Interface.Oxide.Now; if (plugins.Count > 0 && rawAssembly != null) compiledAssembly = new CompiledAssembly(name, plugins.ToArray(), rawAssembly, duration); Interface.Oxide.NextTick(() => callback(this)); }
internal void Completed(byte[] rawAssembly = null) { this.endedAt = Interface.Oxide.Now; if (this.plugins.Count > 0 && rawAssembly != null) { this.compiledAssembly = new CompiledAssembly(this.name, this.plugins.ToArray <CompilablePlugin>(), rawAssembly, this.duration); } Interface.Oxide.NextTick(() => this.callback(this)); }
internal void Completed(byte[] rawAssembly = null) { endedAt = Interface.Oxide.Now; if (plugins.Count > 0 && rawAssembly != null) { compiledAssembly = new CompiledAssembly(name, plugins.ToArray(), rawAssembly, duration); } Interface.Oxide.NextTick(() => callback(this)); }
internal void OnCompilationSucceeded(CompiledAssembly compiledAssembly) { if (timeoutTimer == null) { Interface.Oxide.LogWarning($"Ignored unexpected plugin compilation: {Name}"); return; } timeoutTimer?.Destroy(); timeoutTimer = null; IsCompilationNeeded = false; CompilationQueuedAt = 0f; CompiledAssembly = compiledAssembly; CompileCallback?.Invoke(true); }
private void AddDependency(CompilablePlugin plugin) { if (plugin.IsLoading || this.plugins.Contains(plugin) || this.queuedPlugins.Contains(plugin)) { return; } CompiledAssembly compiledAssembly = plugin.CompiledAssembly; if (compiledAssembly == null || compiledAssembly.IsOutdated()) { this.Add(plugin); } else { this.referencedPlugins.Add(plugin.Name); if (!this.references.ContainsKey(compiledAssembly.Name)) { this.references[compiledAssembly.Name] = new CompilerFile(compiledAssembly.Name, compiledAssembly.RawAssembly); return; } } }
private void AddDependency(CompilablePlugin plugin) { if (plugin.IsLoading || plugins.Contains(plugin) || queuedPlugins.Contains(plugin)) { return; } CompiledAssembly compiledDependency = plugin.CompiledAssembly; if (compiledDependency != null && !compiledDependency.IsOutdated()) { // The dependency already has a compiled assembly which is up to date referencedPlugins.Add(plugin.Name); if (!references.ContainsKey(compiledDependency.Name)) { references[compiledDependency.Name] = new CompilerFile(compiledDependency.Name, compiledDependency.RawAssembly); } } else { // The dependency needs to be compiled Add(plugin); } }
public void LoadPlugin(Action<CSharpPlugin> callback = null) { if (CompiledAssembly == null) { Interface.Oxide.LogError("Load called before a compiled assembly exists: " + Name); RemoteLogger.Error("Load called before a compiled assembly exists: " + Name); IsReloading = false; return; } loadCallback = callback; CompiledAssembly.LoadAssembly(loaded => { IsReloading = false; if (!loaded) { if (callback != null) callback(null); return; } if (CompilerErrors != null) { InitFailed("Unable to load " + ScriptName + ". " + CompilerErrors); return; } var type = CompiledAssembly.LoadedAssembly.GetType("Oxide.Plugins." + Name); if (type == null) { InitFailed("Unable to find main plugin class: " + Name); return; } CSharpPlugin plugin = null; try { plugin = Activator.CreateInstance(type) as CSharpPlugin; } catch (MissingMethodException) { InitFailed("Main plugin class should not have a constructor defined: " + Name); return; } catch (TargetInvocationException invocation_exception) { var ex = invocation_exception.InnerException; InitFailed("Unable to load " + ScriptName + ". " + ex.ToString()); return; } catch (Exception ex) { InitFailed("Unable to load " + ScriptName + ". " + ex.ToString()); return; } if (plugin == null) { RemoteLogger.Error("Plugin assembly failed to load: " + ScriptName); InitFailed("Plugin assembly failed to load: " + ScriptName); return; } plugin.SetPluginInfo(ScriptName, ScriptPath); plugin.Watcher = Extension.Watcher; if (!Interface.Oxide.PluginLoaded(plugin)) { InitFailed(); return; } if (!CompiledAssembly.IsBatch) LastGoodAssembly = CompiledAssembly; if (callback != null) callback(plugin); }); }
private void OnPluginFailed() { if (LastGoodAssembly == null) { Interface.Oxide.LogInfo("No previous version to rollback plugin: {0}", ScriptName); return; } Interface.Oxide.LogInfo("Rolling back plugin to last good version: {0}", ScriptName); CompiledAssembly = LastGoodAssembly; CompilerErrors = null; LoadPlugin(); }
public void OnCompilationSucceeded(CompiledAssembly compiled_assembly) { compilationQueuedAt = 0f; CompiledAssembly = compiled_assembly; compileCallback(true); }
private void CompileAssembly(CompilablePlugin[] plugs) { foreach (var pl in plugs) pl.OnCompilationStarted(compiler); var plugins = new List<CompilablePlugin>(plugs); compiler.Compile(plugins, (assembly_name, raw_assembly, duration) => { if (plugins.Count > 1 && raw_assembly == null) { var plugin_names = plugins.Select(pl => pl.Name); var standalone_plugins = plugins.Where(pl => !pl.Requires.Any(r => plugin_names.Contains(r))).ToArray(); foreach (var plugin in standalone_plugins) plugins.Remove(plugin); foreach (var plugin in plugins) { plugin.OnCompilationFailed(); PluginErrors[plugin.Name] = "Batch containing dependencies failed to compile"; } if (standalone_plugins.Length < 1) { Interface.Oxide.LogError($"A batch of {plugins.Count} plugins failed to compile"); return; } Interface.Oxide.LogError($"A batch of {plugins.Count} plugins failed to compile, attempting to compile separately"); foreach (var plugin in standalone_plugins) CompileAssembly(new[] { plugin }); return; } if (raw_assembly == null) { var plugin = plugins[0]; plugin.OnCompilationFailed(); PluginErrors[plugin.Name] = "Failed to compile: " + plugin.CompilerErrors; Interface.Oxide.LogError("{0} plugin failed to compile!", plugin.ScriptName); Interface.Oxide.LogError(plugin.CompilerErrors); RemoteLogger.Warning($"{plugin.ScriptName} plugin failed to compile!\n{plugin.CompilerErrors}"); } else { var compiled_plugins = plugins.Where(pl => pl.CompilerErrors == null).ToList(); var compiled_names = compiled_plugins.Select(pl => pl.Name).ToArray(); CompiledAssembly compiled_assembly = null; if (compiled_plugins.Count > 0) { var verb = compiled_plugins.Count > 1 ? "were" : "was"; Interface.Oxide.LogInfo($"{compiled_names.ToSentence()} {verb} compiled successfully in {Math.Round(duration * 1000f)}ms"); compiled_assembly = new CompiledAssembly(assembly_name, compiled_plugins.ToArray(), raw_assembly); } foreach (var plugin in plugins) { if (plugin.CompilerErrors == null) { plugin.OnCompilationSucceeded(compiled_assembly); } else { plugin.OnCompilationFailed(); PluginErrors[plugin.Name] = "Failed to compile: " + plugin.CompilerErrors; Interface.Oxide.LogError($"Error while compiling {plugin.CompilerErrors}"); } } } }); }
internal void LoadPlugin(Action <CSharpPlugin> callback = null) { if (CompiledAssembly == null) { Interface.Oxide.LogError("Load called before a compiled assembly exists: {0}", Name); //RemoteLogger.Error($"Load called before a compiled assembly exists: {Name}"); return; } LoadCallback = callback; CompiledAssembly.LoadAssembly(loaded => { if (!loaded) { callback?.Invoke(null); return; } if (CompilerErrors != null) { InitFailed($"Unable to load {ScriptName}. {CompilerErrors}"); return; } var type = CompiledAssembly.LoadedAssembly.GetType($"Oxide.Plugins.{Name}"); if (type == null) { InitFailed($"Unable to find main plugin class: {Name}"); return; } CSharpPlugin plugin; try { plugin = Activator.CreateInstance(type) as CSharpPlugin; } catch (MissingMethodException) { InitFailed($"Main plugin class should not have a constructor defined: {Name}"); return; } catch (TargetInvocationException invocationException) { var ex = invocationException.InnerException; InitFailed($"Unable to load {ScriptName}. {ex.ToString()}"); return; } catch (Exception ex) { InitFailed($"Unable to load {ScriptName}. {ex.ToString()}"); return; } if (plugin == null) { //RemoteLogger.Error($"Plugin assembly failed to load: {ScriptName}"); InitFailed($"Plugin assembly failed to load: {ScriptName}"); return; } if (!plugin.SetPluginInfo(ScriptName, ScriptPath)) { InitFailed(); return; } plugin.Watcher = Extension.Watcher; plugin.Loader = Loader; if (!Interface.Oxide.PluginLoaded(plugin)) { InitFailed(); return; } if (!CompiledAssembly.IsBatch) { LastGoodAssembly = CompiledAssembly; } callback?.Invoke(plugin); }); }
internal void LoadPlugin(Action<CSharpPlugin> callback = null) { if (CompiledAssembly == null) { Interface.Oxide.LogError("Load called before a compiled assembly exists: {0}", Name); RemoteLogger.Error($"Load called before a compiled assembly exists: {Name}"); return; } LoadCallback = callback; CompiledAssembly.LoadAssembly(loaded => { if (!loaded) { callback?.Invoke(null); return; } if (CompilerErrors != null) { InitFailed($"Unable to load {ScriptName}. {CompilerErrors}"); return; } var type = CompiledAssembly.LoadedAssembly.GetType($"Oxide.Plugins.{Name}"); if (type == null) { InitFailed($"Unable to find main plugin class: {Name}"); return; } CSharpPlugin plugin; try { plugin = Activator.CreateInstance(type) as CSharpPlugin; } catch (MissingMethodException) { InitFailed($"Main plugin class should not have a constructor defined: {Name}"); return; } catch (TargetInvocationException invocationException) { var ex = invocationException.InnerException; InitFailed($"Unable to load {ScriptName}. {ex.ToString()}"); return; } catch (Exception ex) { InitFailed($"Unable to load {ScriptName}. {ex.ToString()}"); return; } if (plugin == null) { RemoteLogger.Error($"Plugin assembly failed to load: {ScriptName}"); InitFailed($"Plugin assembly failed to load: {ScriptName}"); return; } plugin.SetPluginInfo(ScriptName, ScriptPath); plugin.Watcher = Extension.Watcher; plugin.Loader = Loader; if (!Interface.Oxide.PluginLoaded(plugin)) { InitFailed(); return; } if (!CompiledAssembly.IsBatch) LastGoodAssembly = CompiledAssembly; callback?.Invoke(plugin); }); }
internal void OnCompilationSucceeded(CompiledAssembly compiled_assembly) { IsCompilationNeeded = false; compilationQueuedAt = 0f; CompiledAssembly = compiled_assembly; compileCallback?.Invoke(true); }
private void PatchAssembly(Action <byte[]> callback) { Action action1 = null; if (this.isPatching) { Interface.Oxide.LogWarning("Already patching plugin assembly: {0} (ignoring)", new object[] { this.PluginNames.ToSentence <string>() }); return; } float now = Interface.Oxide.Now; this.isPatching = true; ThreadPool.QueueUserWorkItem((object _) => { AssemblyDefinition assemblyDefinition; try { using (MemoryStream memoryStream = new MemoryStream(this.RawAssembly)) { assemblyDefinition = AssemblyDefinition.ReadAssembly(memoryStream); } ConstructorInfo constructor = typeof(UnauthorizedAccessException).GetConstructor(new Type[] { typeof(string) }); MethodReference methodReference1 = assemblyDefinition.MainModule.Import(constructor); Action <TypeDefinition> methods = null; methods = (TypeDefinition type) => { string fullName; string str; foreach (MethodDefinition method in type.Methods) { bool flag = false; if (method.Body != null) { bool flag1 = false; foreach (VariableDefinition variable in method.Body.Variables) { if (!CompiledAssembly.IsNamespaceBlacklisted(variable.VariableType.FullName)) { continue; } Mono.Cecil.Cil.MethodBody methodBody = new Mono.Cecil.Cil.MethodBody(method); methodBody.Instructions.Add(Instruction.Create(OpCodes.Ldstr, string.Concat("System access is restricted, you are not allowed to use ", variable.VariableType.FullName))); methodBody.Instructions.Add(Instruction.Create(OpCodes.Newobj, methodReference1)); methodBody.Instructions.Add(Instruction.Create(OpCodes.Throw)); method.Body = methodBody; flag1 = true; break; } if (flag1) { continue; } Collection <Instruction> instructions = method.Body.Instructions; ILProcessor lProcessor = method.Body.GetILProcessor(); Instruction instruction = instructions.First <Instruction>(); for (int i = 0; i < instructions.Count && !flag; i++) { Instruction item = instructions[i]; if (item.OpCode == OpCodes.Ldtoken) { IMetadataTokenProvider operand = item.Operand as IMetadataTokenProvider; str = (operand != null ? operand.ToString() : null); string str1 = str; if (CompiledAssembly.IsNamespaceBlacklisted(str1)) { lProcessor.InsertBefore(instruction, Instruction.Create(OpCodes.Ldstr, string.Concat("System access is restricted, you are not allowed to use ", str1))); lProcessor.InsertBefore(instruction, Instruction.Create(OpCodes.Newobj, methodReference1)); lProcessor.InsertBefore(instruction, Instruction.Create(OpCodes.Throw)); flag = true; } } else if (item.OpCode == OpCodes.Call || item.OpCode == OpCodes.Calli || item.OpCode == OpCodes.Callvirt || item.OpCode == OpCodes.Ldftn) { MethodReference methodReference = item.Operand as MethodReference; string str2 = (methodReference != null ? methodReference.DeclaringType.FullName : null); if (str2 == "System.Type" && methodReference.Name == "GetType" || CompiledAssembly.IsNamespaceBlacklisted(str2)) { lProcessor.InsertBefore(instruction, Instruction.Create(OpCodes.Ldstr, string.Concat("System access is restricted, you are not allowed to use ", str2))); lProcessor.InsertBefore(instruction, Instruction.Create(OpCodes.Newobj, methodReference1)); lProcessor.InsertBefore(instruction, Instruction.Create(OpCodes.Throw)); flag = true; } } else if (item.OpCode == OpCodes.Ldfld) { FieldReference fieldReference = item.Operand as FieldReference; fullName = (fieldReference != null ? fieldReference.FieldType.FullName : null); string str3 = fullName; if (CompiledAssembly.IsNamespaceBlacklisted(str3)) { lProcessor.InsertBefore(instruction, Instruction.Create(OpCodes.Ldstr, string.Concat("System access is restricted, you are not allowed to use ", str3))); lProcessor.InsertBefore(instruction, Instruction.Create(OpCodes.Newobj, methodReference1)); lProcessor.InsertBefore(instruction, Instruction.Create(OpCodes.Throw)); flag = true; } } } } else if (method.HasPInvokeInfo) { MethodDefinition attributes = method; attributes.Attributes = attributes.Attributes & (Mono.Cecil.MethodAttributes.MemberAccessMask | Mono.Cecil.MethodAttributes.Private | Mono.Cecil.MethodAttributes.FamANDAssem | Mono.Cecil.MethodAttributes.Assembly | Mono.Cecil.MethodAttributes.Family | Mono.Cecil.MethodAttributes.FamORAssem | Mono.Cecil.MethodAttributes.Public | Mono.Cecil.MethodAttributes.Static | Mono.Cecil.MethodAttributes.Final | Mono.Cecil.MethodAttributes.Virtual | Mono.Cecil.MethodAttributes.HideBySig | Mono.Cecil.MethodAttributes.VtableLayoutMask | Mono.Cecil.MethodAttributes.NewSlot | Mono.Cecil.MethodAttributes.CheckAccessOnOverride | Mono.Cecil.MethodAttributes.Abstract | Mono.Cecil.MethodAttributes.SpecialName | Mono.Cecil.MethodAttributes.UnmanagedExport | Mono.Cecil.MethodAttributes.RTSpecialName | Mono.Cecil.MethodAttributes.HasSecurity | Mono.Cecil.MethodAttributes.RequireSecObject); Mono.Cecil.Cil.MethodBody methodBody1 = new Mono.Cecil.Cil.MethodBody(method); methodBody1.Instructions.Add(Instruction.Create(OpCodes.Ldstr, "PInvoke access is restricted, you are not allowed to use PInvoke")); methodBody1.Instructions.Add(Instruction.Create(OpCodes.Newobj, methodReference1)); methodBody1.Instructions.Add(Instruction.Create(OpCodes.Throw)); method.Body = methodBody1; } if (!flag) { continue; } Mono.Cecil.Cil.MethodBody body = method.Body; if (body != null) { body.OptimizeMacros(); } else { } } foreach (TypeDefinition nestedType in type.NestedTypes) { methods(nestedType); } }; foreach (TypeDefinition typeDefinition in assemblyDefinition.MainModule.Types) { methods(typeDefinition); if (this.IsCompilerGenerated(typeDefinition)) { continue; } if (typeDefinition.Namespace != "Oxide.Plugins") { if (!(typeDefinition.FullName != "<Module>") || this.PluginNames.Any <string>((string plugin) => typeDefinition.FullName.StartsWith(string.Concat("Oxide.Plugins.", plugin)))) { continue; } Interface.Oxide.LogWarning(((int)this.PluginNames.Length == 1 ? string.Concat(this.PluginNames[0], " has polluted the global namespace by defining ", typeDefinition.FullName) : string.Concat("A plugin has polluted the global namespace by defining ", typeDefinition.FullName)), Array.Empty <object>()); } else if (!this.PluginNames.Contains <string>(typeDefinition.Name)) { Interface.Oxide.LogWarning(((int)this.PluginNames.Length == 1 ? string.Concat(this.PluginNames[0], " has polluted the global namespace by defining ", typeDefinition.Name) : string.Concat("A plugin has polluted the global namespace by defining ", typeDefinition.Name)), Array.Empty <object>()); } else { Collection <MethodDefinition> methodDefinitions = typeDefinition.Methods; Func <MethodDefinition, bool> u003cu003e9_204 = CompiledAssembly.< > c.< > 9__20_4; if (u003cu003e9_204 == null) { u003cu003e9_204 = (MethodDefinition m) => { if (m.IsStatic || !m.IsConstructor || m.HasParameters) { return(false); } return(!m.IsPublic); }; CompiledAssembly.< > c.< > 9__20_4 = u003cu003e9_204; } if (methodDefinitions.FirstOrDefault <MethodDefinition>(u003cu003e9_204) == null) { DirectCallMethod directCallMethod = new DirectCallMethod(assemblyDefinition.MainModule, typeDefinition); } else { CompilablePlugin compilablePlugin = this.CompilablePlugins.SingleOrDefault <CompilablePlugin>((CompilablePlugin p) => p.Name == typeDefinition.Name); if (compilablePlugin == null) { continue; } compilablePlugin.CompilerErrors = "Primary constructor in main class must be public"; } } } foreach (TypeDefinition typeDefinition1 in assemblyDefinition.MainModule.Types) { if (typeDefinition1.Namespace != "Oxide.Plugins" || !this.PluginNames.Contains <string>(typeDefinition1.Name)) { continue; } Collection <MethodDefinition> methods1 = typeDefinition1.Methods; Func <MethodDefinition, bool> u003cu003e9_206 = CompiledAssembly.< > c.< > 9__20_6; if (u003cu003e9_206 == null) { u003cu003e9_206 = (MethodDefinition m) => { if (m.IsStatic || m.HasGenericParameters || m.ReturnType.IsGenericParameter || m.IsSetter) { return(false); } return(!m.IsGetter); }; CompiledAssembly.< > c.< > 9__20_6 = u003cu003e9_206; } foreach (MethodDefinition methodDefinition in methods1.Where <MethodDefinition>(u003cu003e9_206)) { foreach (ParameterDefinition parameter in methodDefinition.Parameters) { foreach (CustomAttribute customAttribute in parameter.CustomAttributes) { } } } } using (MemoryStream memoryStream1 = new MemoryStream()) { assemblyDefinition.Write(memoryStream1); this.PatchedAssembly = memoryStream1.ToArray(); } OxideMod oxide = Interface.Oxide; Action u003cu003e9_2 = action1; if (u003cu003e9_2 == null) { Action u003cu003e4_this = () => { this.isPatching = false; callback(this.PatchedAssembly); }; Action action = u003cu003e4_this; action1 = u003cu003e4_this; u003cu003e9_2 = action; } oxide.NextTick(u003cu003e9_2); } catch (Exception exception1) { Exception exception = exception1; Interface.Oxide.NextTick(() => { this.isPatching = false; Interface.Oxide.LogException(string.Concat("Exception while patching: ", this.PluginNames.ToSentence <string>()), exception); callback(null); }); } }); }