<commit_before>﻿using System;
using System.CodeDom.Compiler;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;
using System.Security;
using System.Security.Permissions;
using System.Security.Policy;
using System.Threading;

using Microsoft.CSharp;

// This assembly attribute is needed for dynamic compilation/execution within a secure domain
[assembly: AllowPartiallyTrustedCallers]
namespace MetadataApiCommon
{
    public class RunnableExecutor : MarshalByRefObject
    {
        public RunnableExecutor()
        {}

        public static Assembly CompileCode(string ExecCode, string[] Assemblies)
        {
            CSharpCodeProvider provider   = new CSharpCodeProvider();
            CompilerParameters parameters = new CompilerParameters(Assemblies);

            // parameters.ReferencedAssemblies.Add("MetadataCommonApi.dll");

            parameters.GenerateInMemory   = true;
            parameters.GenerateExecutable = false;

            CompilerResults results = provider.CompileAssemblyFromSource(parameters, ExecCode);

            if (results.Errors.HasErrors)
            {
                StringBuilder sb = new StringBuilder();

                foreach (CompilerError error in results.Errors)
                    sb.AppendLine(String.Format("Error ({0}): {1}", error.ErrorNumber, error.ErrorText));

                throw new InvalidOperationException(sb.ToString());
            }

            Assembly assembly = results.CompiledAssembly;

            return assembly;
        }

        public List<Dictionary<string, string>> CompileAndExecuteCode(string                           UrlParameters, 
                                                                      string                           ExecCode, 
                                                                      List<Dictionary<string, string>> Body)
        {
            var AssemblyNames = (from a in AppDomain.CurrentDomain.GetAssemblies()
                                 where !a.IsDynamic
                                 select a.Location).ToArray();

            return CompileAndExecuteCode(UrlParameters, ExecCode, Body, AssemblyNames);

        }

        public List<Dictionary<string, string>> CompileAndExecuteCode(string                           UrlParameters, 
                                                                      string                           ExecCode, 
                                                                      List<Dictionary<string, string>> Body,
                                                                      string[]                         Assemblies)
        {
            Assembly dynamicAssembly = RunnableExecutor.CompileCode(ExecCode, Assemblies);

            /*
int        StartIndex   = ExecCode.IndexOf(CONST_CLASS_NAME_START_IND) + CONST_CLASS_NAME_START_IND.Length;
int        EndIndex     = ExecCode.IndexOf(CONST_CLASS_NAME_END_IND, StartIndex);
string     ClassName    = ExecCode.Substring(StartIndex, (EndIndex - StartIndex)).Trim();
Type       RunnableType = assembly.GetType(ClassName);
 */

            var typesInAssembly = dynamicAssembly.GetTypes();

            var type = typesInAssembly.First();

            // MethodInfo runMethod = instance.GetMethod("Run");

            return RunnableExecutor.InvokeRunnable(type, Body);
        }

        public static List<Dictionary<string, string>> CompileAndExecuteCodeSafe(string                           UrlParameters, 
                                                                                 string                           ExecCode, 
                                                                                 List<Dictionary<string, string>> Body)
        {
            AppDomain sandbox = null;

            try
            {
                string targetAssemblyPath = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;

                var assemblyNames = (from a in AppDomain.CurrentDomain.GetAssemblies()
                                      where !a.IsDynamic
                                      select a.Location).ToArray();

                Assembly dynamicAssembly = RunnableExecutor.CompileCode(ExecCode, assemblyNames);

                foreach (string tmpAssembly in assemblyNames)
                {
                    if (tmpAssembly.Contains("MetadataApiCommon"))
                    {
                        targetAssemblyPath = tmpAssembly;
                        break;
                    }
                }

                /*
                 * 
                AppDomainSetup setup = new AppDomainSetup() { ApplicationBase = Path.GetDirectoryName(targetAssemblyPath) };

                domain = AppDomain.CreateDomain("Sandbox", null, setup);
                 */

                // sandbox = ProduceSecureDomain(targetAssemblyPath);
                sandbox = ProduceSecureDomain( new string[] { targetAssemblyPath, GetAssemblyDirectory(dynamicAssembly) } );

                /*
                 * 
                foreach (string tmpAssembly in assemblyNames)
                    sandbox.Load(tmpAssembly);
                 */

                var typesInAssembly = dynamicAssembly.GetTypes();

                var type = typesInAssembly.First();

                RunnableExecutor runnableExecutor =
                    (RunnableExecutor)sandbox.CreateInstanceFromAndUnwrap(targetAssemblyPath, "MetadataApiCommon.RunnableExecutor");
<commit_msg>* Getting closer to dynamic compilation within a sandbox app domain.<commit_after>﻿using System;
using System.CodeDom.Compiler;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;
using System.Security;
using System.Security.Permissions;
using System.Security.Policy;
using System.Threading;

using Microsoft.CSharp;

// This assembly attribute is needed for dynamic compilation/execution within a secure domain
[assembly: AllowPartiallyTrustedCallers]
namespace MetadataApiCommon
{
    public class RunnableExecutor : MarshalByRefObject
    {
        public RunnableExecutor()
        {}

        public static Assembly CompileCode(string ExecCode, string[] Assemblies, bool InMemory = true)
        {
            CSharpCodeProvider provider   = new CSharpCodeProvider();
            CompilerParameters parameters = new CompilerParameters(Assemblies);

            // parameters.ReferencedAssemblies.Add("MetadataCommonApi.dll");

            parameters.GenerateInMemory   = InMemory;
            parameters.GenerateExecutable = false;

            CompilerResults results = provider.CompileAssemblyFromSource(parameters, ExecCode);

            if (results.Errors.HasErrors)
            {
                StringBuilder sb = new StringBuilder();

                foreach (CompilerError error in results.Errors)
                    sb.AppendLine(String.Format("Error ({0}): {1}", error.ErrorNumber, error.ErrorText));

                throw new InvalidOperationException(sb.ToString());
            }

            Assembly assembly = results.CompiledAssembly;

            return assembly;
        }

        public List<Dictionary<string, string>> CompileAndExecuteCode(string                           UrlParameters, 
                                                                      string                           ExecCode, 
                                                                      List<Dictionary<string, string>> Body)
        {
            var AssemblyNames = (from a in AppDomain.CurrentDomain.GetAssemblies()
                                 where !a.IsDynamic
                                 select a.Location).ToArray();

            return CompileAndExecuteCode(UrlParameters, ExecCode, Body, AssemblyNames);

        }

        public List<Dictionary<string, string>> CompileAndExecuteCode(string                           UrlParameters, 
                                                                      string                           ExecCode, 
                                                                      List<Dictionary<string, string>> Body,
                                                                      string[]                         Assemblies)
        {
            Assembly dynamicAssembly = RunnableExecutor.CompileCode(ExecCode, Assemblies);

            var typesInAssembly = dynamicAssembly.GetTypes();

            var type = typesInAssembly.First();

            return RunnableExecutor.InvokeRunnable(type, Body);
        }

        public static List<Dictionary<string, string>> CompileAndExecuteCodeSafe(string                           UrlParameters, 
                                                                                 string                           ExecCode, 
                                                                                 List<Dictionary<string, string>> Body)
        {
            AppDomain sandbox = null;

            HashSet<string> additionalAssemblyDirs = new HashSet<string>();

            try
            {
                string targetAssemblyPath = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;

                var assemblyNames = (from a in AppDomain.CurrentDomain.GetAssemblies()
                                      where !a.IsDynamic
                                      select a.Location).ToArray();

                foreach (string tmpAssembly in assemblyNames)
                {
                    // additionalAssemblyDirs.Add(Path.GetDirectoryName(tmpAssembly));

                    if (tmpAssembly.Contains("MetadataApiCommon"))
                        targetAssemblyPath = tmpAssembly;
                }

                Assembly dynamicAssembly = RunnableExecutor.CompileCode(ExecCode, assemblyNames, false);

                additionalAssemblyDirs.Add(RunnableExecutor.GetAssemblyDirectory(dynamicAssembly));

                /*
                 * 
                AppDomainSetup setup = new AppDomainSetup() { ApplicationBase = Path.GetDirectoryName(targetAssemblyPath) };

                domain = AppDomain.CreateDomain("Sandbox", null, setup);
                 */

                // sandbox = ProduceSecureDomain(targetAssemblyPath);
                sandbox = ProduceSecureDomain(additionalAssemblyDirs.ToArray());

                /*
                byte[] assemblyAsArray = null;
                using (MemoryStream stream = new MemoryStream())
                {
                    System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter =
                        new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();

                    formatter.Serialize(stream, dynamicAssembly);

                    assemblyAsArray = stream.ToArray();
                }

                if (assemblyAsArray != null)
                    sandbox.Load(assemblyAsArray);
                 */

                var typesInAssembly = dynamicAssembly.GetTypes();

                var type = typesInAssembly.First();

                RunnableExecutor runnableExecutor =
                    (RunnableExecutor)sandbox.CreateInstanceFromAndUnwrap(targetAssemblyPath, "MetadataApiCommon.RunnableExecutor");

{'fraction_non_alphanumeric': 0.06811940827354061, 'fraction_numerical': 0.0003543272211887678, 'mean_word_length': 1.5072174106151455, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 50, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7374805', 'n_tokens_mistral': 2413, 'n_tokens_neox': 2206, 'n_words': 492}