diff --git a/umbraco.MacroEngines.Iron/DLRScriptingEngine.cs b/umbraco.MacroEngines.Iron/DLRScriptingEngine.cs new file mode 100644 index 0000000000..ca24f0f9b5 --- /dev/null +++ b/umbraco.MacroEngines.Iron/DLRScriptingEngine.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using umbraco.cms.businesslogic.macro; +using umbraco.interfaces; +using umbraco.IO; +using umbraco.MacroEngines.Scripting; + +namespace umbraco.MacroEngines +{ + public class DLRScriptingEngine : IMacroEngine + { + #region IMacroEngine Members + + public virtual string Name { + get { return "Umbraco DLR Macro Engine"; } + } + + public virtual IEnumerable SupportedExtensions { + get { return new [] {"py", "rb"}; } + } + + public IEnumerable SupportedUIExtensions { + get { return SupportedExtensions; } + } + + public virtual Dictionary SupportedProperties { + get { throw new NotImplementedException(); } + } + + public virtual bool Validate(string code, string filePath, INode currentPage, out string errorMessage) { + errorMessage = string.Empty; + return true; + } + + public virtual string Execute(MacroModel macro, INode currentPage) { + var fileEnding = macro.ScriptName.Substring(macro.ScriptName.LastIndexOf('.')).Trim('.'); + var mse = MacroScriptEngine.LoadEngineByFileExtension(fileEnding); + var vars = new SortedDictionary { + {"currentPage", new DynamicNode(currentPage)} + }; + foreach (var prop in macro.Properties) { + vars.Add(prop.Key, prop.Value); + } + mse.ScriptVariables = vars; + return mse.ExecuteFile(IOHelper.MapPath(SystemDirectories.Python + "/" + macro.ScriptName)); + } + + #endregion + } +} \ No newline at end of file diff --git a/umbraco.MacroEngines.Iron/Scripting/MacroScript.cs b/umbraco.MacroEngines.Iron/Scripting/MacroScript.cs new file mode 100644 index 0000000000..2e2a7d23d9 --- /dev/null +++ b/umbraco.MacroEngines.Iron/Scripting/MacroScript.cs @@ -0,0 +1,53 @@ +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using Microsoft.Scripting.Hosting; + +namespace umbraco.MacroEngines.Scripting +{ + public class MacroScript { + + public static string Execute(string script, string scriptType, Hashtable variables) { + var mse = new MacroScriptEngine(scriptType); + mse.ScriptVariables = ConvertHashTable(variables); + mse.Script = script; + return mse.Execute(); + } + + public static string Evaluate(string script, string scriptType, Hashtable variables) + { + var mse = new MacroScriptEngine(scriptType); + mse.ScriptVariables = ConvertHashTable(variables); + mse.Script = script; + return mse.Evaluate(); + } + + public static string ExecuteFile(string path, Hashtable variables) { + var fileEnding = path.Substring(path.LastIndexOf('.')).Trim('.'); + var mse = MacroScriptEngine.LoadEngineByFileExtension(fileEnding); + mse.ScriptVariables = ConvertHashTable(variables); + return mse.ExecuteFile(path); + } + + //friendly helpers.... + public static string ExecutePython(string script, Hashtable variables) { + return Execute(script, "python", variables); + } + + public static string ExecuteRuby(string script, Hashtable variables) { + return Execute(script, "ruby", variables); + } + + private static SortedDictionary ConvertHashTable(Hashtable ht) { + var retval = new SortedDictionary(); + foreach (DictionaryEntry de in ht) { + retval.Add(de.Key.ToString(), de.Value); + } + return retval; + } + + public static List GetAvailableLanguages() { + return ScriptRuntimeSetup.ReadConfiguration().LanguageSetups.ToList(); + } + } +} diff --git a/umbraco.MacroEngines.Iron/Scripting/ScriptEngine.cs b/umbraco.MacroEngines.Iron/Scripting/ScriptEngine.cs new file mode 100644 index 0000000000..bcec3b5ab8 --- /dev/null +++ b/umbraco.MacroEngines.Iron/Scripting/ScriptEngine.cs @@ -0,0 +1,199 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using Microsoft.Scripting; +using Microsoft.Scripting.Hosting; + +namespace umbraco.MacroEngines.Scripting +{ + internal class MacroScriptEngine + { + ScriptRuntime m_runTime; + ScriptEngine m_engine; + ExceptionOperations m_exceptionOperations; + SortedDictionary m_inputVariables; + SortedDictionary m_outputVariables; + string m_script; + MemoryStream m_output; + + internal MacroScriptEngine() { } + + internal MacroScriptEngine(string scriptType) + { + loadRunTime(); + m_engine = m_runTime.GetEngine(scriptType); + m_exceptionOperations = m_engine.GetService(); + } + + internal static MacroScriptEngine LoadEngineByFileExtension(string fileExtension) + { + MacroScriptEngine mse = new MacroScriptEngine(); + mse.loadRunTime(); + mse.m_engine = mse.m_runTime.GetEngineByFileExtension(fileExtension); + mse.m_exceptionOperations = mse.m_engine.GetService(); + return mse; + } + + internal static MacroScriptEngine GetEngineByType(string scriptType) + { + MacroScriptEngine mse = new MacroScriptEngine(); + mse.loadRunTime(); + mse.m_engine = mse.m_runTime.GetEngine(scriptType); + mse.m_exceptionOperations = mse.m_engine.GetService(); + return mse; + } + + private void loadRunTime() + { + m_output = new MemoryStream(); + m_runTime = ScriptRuntime.CreateFromConfiguration(); + + m_runTime.IO.SetOutput(m_output, new StreamWriter(m_output)); + m_runTime.IO.SetErrorOutput(m_output, new StreamWriter(m_output)); + + Assembly pluginsAssembly = Assembly.LoadFile(IO.IOHelper.MapPath(IO.SystemDirectories.Bin + "/umbraco.dll")); + m_runTime.LoadAssembly(pluginsAssembly); + + m_runTime.LoadAssembly(typeof(String).Assembly); + m_runTime.LoadAssembly(typeof(Uri).Assembly); + m_runTime.LoadAssembly(typeof(umbraco.presentation.nodeFactory.Node).Assembly); + } + + + internal SortedDictionary ScriptVariables + { + set { m_inputVariables = value; } + } + + internal SortedDictionary OutPutVariables + { + get { return m_outputVariables; } + } + + internal string Script + { + set { m_script = value; } + } + + internal ExceptionOperations ExceptionOperations + { + get { return m_exceptionOperations; } + } + + internal string Evaluate() + { + //Create structures + SourceCodeKind sc = SourceCodeKind.Expression; + ScriptSource source = m_engine.CreateScriptSourceFromString(m_script, sc); + ScriptScope scope = m_engine.CreateScope(); + + //Fill input variables + foreach (KeyValuePair variable in m_inputVariables) + { + scope.SetVariable(variable.Key, variable.Value); + } + + string result = ""; + + try + { + object r = source.Execute(scope); + + if (r != null) + result = r.ToString(); + } + catch (Exception e) + { + umbraco.BusinessLogic.Log.Add(umbraco.BusinessLogic.LogTypes.Debug, -1, e.ToString()); + result = m_exceptionOperations.FormatException(e); + } + + return result; + } + + internal string Execute() + { + SourceCodeKind sc = SourceCodeKind.Statements; + ScriptSource source = m_engine.CreateScriptSourceFromString(m_script, sc); + ScriptScope scope = m_engine.CreateScope(); + + //Fill input variables + foreach (KeyValuePair variable in m_inputVariables) + { + scope.SetVariable(variable.Key, variable.Value); + } + + source.Execute(scope); + + m_outputVariables = new SortedDictionary(); + foreach (string variable in scope.GetVariableNames()) + { + m_outputVariables.Add(variable, scope.GetVariable(variable)); + } + + return ReadFromStream(m_output); + } + + internal string ExecuteFile(string path) + { + string rbCode; + + // OpenText will strip the BOM and keep the Unicode intact + using (var rdr = File.OpenText(path)) + { + rbCode = rdr.ReadToEnd(); + } + + m_script = rbCode; + return Execute(); + } + + internal SortedDictionary _Execute() + { + //Create structures + SourceCodeKind sc = SourceCodeKind.Statements; + ScriptSource source = m_engine.CreateScriptSourceFromString(m_script, sc); + ScriptScope scope = m_engine.CreateScope(); + + //Fill input variables + foreach (KeyValuePair variable in m_inputVariables) + { + scope.SetVariable(variable.Key, variable.Value); + } + + SortedDictionary outputVariables = new SortedDictionary(); + //Execute the script + try + { + + source.Execute(scope); + //Recover variables + foreach (string variable in scope.GetVariableNames()) + { + outputVariables.Add(variable, scope.GetVariable(variable)); + } + } + catch (Exception e) + { + string error = m_exceptionOperations.FormatException(e); + //Do something with the pretty printed error + throw; + } + return outputVariables; + } + + private static string ReadFromStream(MemoryStream ms) + { + int length = (int)ms.Length; + Byte[] bytes = new Byte[length]; + + ms.Seek(0, SeekOrigin.Begin); + ms.Read(bytes, 0, (int)ms.Length); + + return Encoding.GetEncoding("utf-8").GetString(bytes, 0, (int)ms.Length); + } + } +} diff --git a/umbraco.MacroEngines.Iron/umbraco.MacroEngines.Iron.csproj b/umbraco.MacroEngines.Iron/umbraco.MacroEngines.Iron.csproj new file mode 100644 index 0000000000..65975377ab --- /dev/null +++ b/umbraco.MacroEngines.Iron/umbraco.MacroEngines.Iron.csproj @@ -0,0 +1,81 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {98CBA7E2-1B62-497C-8AA3-B868704068D7} + Library + Properties + umbraco.MacroEngines.Iron + umbraco.MacroEngines.Iron + v4.0 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\foreign dlls\DLR 4.0\Microsoft.Scripting.dll + + + + + + + + + + + + + + + + + + {89C09045-1064-466B-B94A-DB3AFE2A5853} + umbraco.MacroEngines + + + {E469A9CE-1BEC-423F-AC44-713CD72457EA} + umbraco.businesslogic + + + {CCD75EC3-63DB-4184-B49D-51C1DD337230} + umbraco.cms + + + {511F6D8D-7717-440A-9A57-A507E9A8B27F} + umbraco.interfaces + + + {651E1350-91B6-44B7-BD60-7207006D7003} + umbraco.presentation + + + + + \ No newline at end of file