//--- Constructors --- public DekiScriptComparer(DekiScriptRuntime runtime, DekiScriptExpression compare) { if(compare == null) { throw new ArgumentNullException("compare"); } _runtime = runtime; _compare = compare; _values = new DekiScriptMap(); _env = runtime.CreateEnv(); _env.Vars.Add(DekiScriptRuntime.DEFAULT_ID, _values); }
//--- Constructors --- public DekiScriptCaseBlock(DekiScriptExpression[] conditions, DekiScriptExpression body, bool isBlock) { if(conditions == null) { throw new ArgumentNullException("conditions"); } if(body == null) { throw new ArgumentNullException("body"); } this.Conditions = conditions; this.Body = body; IsBlock = isBlock; }
public DekiScriptExpressionInvocationTarget(DreamAccess access, DekiScriptParameter[] parameters, DekiScriptExpression expr, DekiScriptEnv env) { if(parameters == null) { throw new ArgumentNullException("parameters"); } if(expr == null) { throw new ArgumentNullException("expr"); } this.Access = access; this.Parameters = parameters; this.Expression = expr; _env = env; }
public void Test(DekiScriptExpression expr, string resultValue, Type expectedType, bool safe) { var env = Runtime.CreateEnv(); env.Vars.Add(DekiScriptEnv.SAFEMODE, DekiScriptExpression.Constant(safe)); DekiScriptExpression result = Runtime.Evaluate(expr, safe ? DekiScriptEvalMode.EvaluateSafeMode : DekiScriptEvalMode.Evaluate, env); Assert.IsAssignableFrom(expectedType, result); string value; if(result is DekiScriptString) { value = ((DekiScriptString)result).Value; } else if(result is DekiScriptXml) { value = ((DekiScriptXml)result).Value.ToString(); } else { value = result.ToString(); } Assert.AreEqual(resultValue, value); }
public static object ListReduce( [DekiScriptParam("list value")] ArrayList list, [DekiScriptParam("expression to compute combined value (use '$value' and '$item' to refer to the current value and item, respectively)")] string expression, [DekiScriptParam("starting value (default: nil)", true)] object value, DekiScriptRuntime runtime ) { DekiScriptExpression expr = DekiScriptParser.Parse(new Location("list.reduce(expression)"), expression); foreach (object entry in list) { DekiScriptEnv env = runtime.CreateEnv(); DekiScriptMap values = new DekiScriptMap(); values.Add("value", DekiScriptLiteral.FromNativeValue(value)); values.Add("item", DekiScriptLiteral.FromNativeValue(entry)); env.Vars.Add(DekiScriptRuntime.DEFAULT_ID, values); value = runtime.Evaluate(expr, DekiScriptEvalMode.EvaluateSafeMode, env).NativeValue; } return(value); }
public static Hashtable MapApply( [DekiScriptParam("map value")] Hashtable map, [DekiScriptParam("expression to apply (use '$' to refer to the item)")] string expression, DekiScriptRuntime runtime ) { DekiScriptExpression expr = DekiScriptParser.Parse(new Location("map.apply(expression)"), expression); Hashtable result = new Hashtable(StringComparer.OrdinalIgnoreCase); foreach (DictionaryEntry entry in map) { DekiScriptMap keyvalue = new DekiScriptMap(); keyvalue.Add("key", DekiScriptLiteral.FromNativeValue(entry.Key)); keyvalue.Add("value", DekiScriptLiteral.FromNativeValue(Eval(entry.Value, runtime))); DekiScriptEnv env = runtime.CreateEnv(); env.Vars.Add(DekiScriptRuntime.DEFAULT_ID, keyvalue); result.Add(entry.Key, runtime.Evaluate(expr, DekiScriptEvalMode.EvaluateSafeMode, env)); } return(result); }
public static int ListCount( [DekiScriptParam("list value")] ArrayList list, [DekiScriptParam("condition to execute for each item (use '$' to refer to the item)")] string condition, DekiScriptRuntime runtime ) { DekiScriptExpression expr = DekiScriptParser.Parse(new Location("list.count(condition)"), condition); int count = 0; foreach (object entry in list) { DekiScriptEnv env = runtime.CreateEnv(); env.Vars.Add(DekiScriptRuntime.DEFAULT_ID, DekiScriptLiteral.FromNativeValue(entry)); DekiScriptLiteral test = runtime.Evaluate(expr, DekiScriptEvalMode.EvaluateSafeMode, env); if (!test.IsNilFalseZero) { ++count; } } return(count); }
private static bool TryParseDekiScriptExpression(string ctor, DekiScriptEnv env, DekiScriptRuntime runtime, ref int i, out string value) { string source = ParseExpression(ctor, null, ParseMode.EXPRESSION, false, env, runtime, null, ref i); if ((i >= ctor.Length) || (ctor[i] != '}')) { value = null; return(false); } // try to parse and execute the dekiscript fragment try { source = source.Substring(1, source.Length - 2); DekiScriptExpression dekiscript = DekiScriptParser.Parse(new Location("jem"), source); DekiScriptLiteral result = runtime.Evaluate(dekiscript, DekiScriptEvalMode.EvaluateSafeMode, env); value = DekiScriptLibrary.JsonEmit(result.NativeValue); } catch (Exception e) { // execution failed; convert exception into a javascript comment value = "alert(\"ERROR in DekiScript expression:\\n---------------------------\\n\\n\" + " + e.GetCoroutineStackTrace().QuoteString() + ")"; } return(true); }
public DekiScriptOutputBuffer.Range Visit(DekiScriptUnary expr, DekiScriptExpressionEvaluationState state) { switch (expr.OpCode) { case DekiScriptUnary.Op.Negate: return(state.Push(DekiScriptExpression.Constant(-state.Pop(expr.Value.VisitWith(this, state)).AsNumber()))); case DekiScriptUnary.Op.LogicalNot: return(state.Push(DekiScriptExpression.Constant(state.Pop(expr.Value.VisitWith(this, state)).IsNilFalseZero))); case DekiScriptUnary.Op.TypeOf: return(state.Push(DekiScriptExpression.Constant(state.Pop(expr.Value.VisitWith(this, state)).ScriptTypeName))); case DekiScriptUnary.Op.Length: { DekiScriptLiteral value = state.Pop(expr.Value.VisitWith(this, state)); switch (value.ScriptType) { case DekiScriptType.NIL: return(state.Push(DekiScriptExpression.Constant(0))); case DekiScriptType.LIST: return(state.Push(DekiScriptExpression.Constant(((DekiScriptList)value).Value.Count))); case DekiScriptType.STR: return(state.Push(DekiScriptExpression.Constant(((DekiScriptString)value).Value.Length))); case DekiScriptType.MAP: return(state.Push(DekiScriptExpression.Constant(((DekiScriptMap)value).Value.Count))); case DekiScriptType.XML: return(state.Push(DekiScriptExpression.Constant(((DekiScriptXml)value).Value.ListLength))); default: return(DekiScriptOutputBuffer.Range.Empty); } } } throw new InvalidOperationException("invalid op code:" + expr.OpCode); }
public DekiScriptLiteral GetMagicId(string id) { DekiScriptLiteral result = DekiScriptNil.Value; // check if magic IDs map already exists; if not, create one if (_magicIds == null) { _magicIds = new DekiScriptMap(); } else { result = _magicIds[id]; } // check if a magic ID was found; if not, create one if (result.IsNil) { result = DekiScriptExpression.Constant(id + "_" + StringUtil.CreateAlphaNumericKey(8)); _magicIds.Add(id, result); } return(result); }
public void Dom_evaluation_with_static_content() { XDoc doc = new XDoc("html").UsePrefix("eval", "http://mindtouch.com/2007/dekiscript") .Start("body") .Start("div").Attr("block", "var x = string.toupper('foo')") .Elem("eval:expr", "x .. 3; string.nbsp") .End() .End(); // parse node DekiScriptExpression node = DekiScriptParser.Parse(doc); Assert.AreEqual("<html><body>(discard (var x = string.toupper(\"foo\")); <div>(x .. 3; string.nbsp)</div>) !! web.showerror(__error)</body></html> !! web.showerror(__error)", node.ToString()); // TODO (steveb): disabled the partial evaluation test for now // partial evaluation //node = node.Optimize(DekiScriptEvalMode.Evaluate, DekiScriptEnv.Create()); //Assert.AreEqual("<html><body><div>\"FOO3�\"; </div></body></html>", node.ToString()); // full evaluation //XDoc value = node.Evaluate(DekiScriptEvalMode.Evaluate, DekiScriptEnv.Create()).AsEmbeddableXml(false); //Assert.AreEqual("<html><body><div>FOO3 </div></body></html>", value.ToXHtml()); }
public void Test(DekiScriptExpression expr, string resultValue, Type expectedType, bool safe) { var env = Runtime.CreateEnv(); env.Vars.Add(DekiScriptEnv.SAFEMODE, DekiScriptExpression.Constant(safe)); DekiScriptExpression result = Runtime.Evaluate(expr, safe ? DekiScriptEvalMode.EvaluateSafeMode : DekiScriptEvalMode.Evaluate, env); Assert.IsAssignableFrom(expectedType, result); string value; if (result is DekiScriptString) { value = ((DekiScriptString)result).Value; } else if (result is DekiScriptXml) { value = ((DekiScriptXml)result).Value.ToString(); } else { value = result.ToString(); } Assert.AreEqual(resultValue, value); }
void Primary(out DekiScriptExpression expr) { DekiScriptExpression inner = null; expr = null; string name = null; Location location = t.Location; if (StartOf(9)) { Literal(out expr); } else if (la.kind == 22) { Get(); Statements(out expr); Expect(23); expr = DekiScriptExpression.Block(location, new[] { expr }); } else if (la.kind == 1) { Get(); expr = DekiScriptExpression.Id(location, t.val); } else SynErr(83); while (StartOf(10)) { if (la.kind == 63) { Get(); location = t.Location; if (StartOf(11)) { AnyName(out name); expr = DekiScriptExpression.Access(location, expr, DekiScriptExpression.Constant(name)); } else if (la.kind == 22) { ArgList(out location, out inner); expr = DekiScriptExpression.Curry(location, expr, inner); } else if (la.kind == 9) { Map(out location, out inner); expr = DekiScriptExpression.Curry(location, expr, inner); } else SynErr(84); } else if (la.kind == 64) { Get(); location = t.Location; Expression(out inner); Expect(65); expr = DekiScriptExpression.Access(location, expr, inner); } else if (la.kind == 22) { ArgList(out location, out inner); expr = DekiScriptExpression.Call(location, expr, inner); } else { Map(out location, out inner); expr = DekiScriptExpression.Call(location, expr, inner); } } }
public void OutputBuffer_image_uri_followed_by_html() { var expr = DekiScriptExpression.Block(Location.None, new[] { DekiScriptExpression.Constant(new XUri("http://foo/index.png")), DekiScriptExpression.Constant(new XDoc("html").Elem("body", "test")) }); _dekiScriptTester.Test( expr, @"<html><body><img src=""http://foo/index.png"" />test</body></html>", typeof(DekiScriptXml), false ); }
void AndExpr(out DekiScriptExpression expr) { DekiScriptExpression inner = null; Location location = Location.None; EqlExpr(out expr); while (la.kind == 40) { Get(); location = t.Location; EqlExpr(out inner); expr = DekiScriptExpression.BinaryOp(location, DekiScriptBinary.Op.LogicalAnd, expr, inner); } }
void EqlExpr(out DekiScriptExpression expr) { DekiScriptExpression inner = null; DekiScriptBinary.Op op = DekiScriptBinary.Op.LeftValue; Location location = Location.None; RelExpr(out expr); while (StartOf(5)) { if (la.kind == 41) { Get(); op = DekiScriptBinary.Op.NotEqual; } else if (la.kind == 42) { Get(); op = DekiScriptBinary.Op.Equal; } else if (la.kind == 43) { Get(); op = DekiScriptBinary.Op.IdentityNotEqual; } else { Get(); op = DekiScriptBinary.Op.IdentityEqual; } location = t.Location; RelExpr(out inner); expr = DekiScriptExpression.BinaryOp(location, op, expr, inner); } }
void NullCoalescingExpr(out DekiScriptExpression expr) { DekiScriptExpression inner = null; Location location = Location.None; OrExpr(out expr); while (la.kind == 38) { Get(); location = t.Location; OrExpr(out inner); expr = DekiScriptExpression.BinaryOp(location, DekiScriptBinary.Op.NullCoalesce, expr, inner); } }
private DekiScriptExpression Html(string container, string tag, string type, DekiScriptExpression expr) { DekiScriptExpression style = DekiScriptExpression.XmlElement(Location, null, DekiScriptExpression.Constant(tag), new[] { new DekiScriptXmlElement.Attribute(Location, null, DekiScriptExpression.Constant("type"), DekiScriptExpression.Constant(type)) }, expr); DekiScriptExpression head = DekiScriptExpression.XmlElement(Location, null, DekiScriptExpression.Constant(container), null, style); DekiScriptExpression html = DekiScriptExpression.XmlElement(Location, null, DekiScriptExpression.Constant("html"), null, head); return html; }
void Xml(out DekiScriptExpression expr) { XmlNode(out expr); }
public static void InitializeCustomDekiScriptHeaders(PageBE page) { var current = DreamContext.Current; DekiScriptMap env = current.GetState <DekiScriptMap>("pageimplicitenv-" + page.ID); // check if we already have an initialized environment if (env == null) { DekiContext deki = DekiContext.Current; DekiInstance instance = deki.Instance; env = new DekiScriptMap(); // add site fields DekiScriptMap siteFields = new DekiScriptMap(); siteFields.Add("name", DekiScriptExpression.Constant(instance.SiteName)); siteFields.Add("host", DekiScriptExpression.Constant(deki.UiUri.Uri.Host)); siteFields.Add("language", DekiScriptExpression.Constant(instance.SiteLanguage)); siteFields.Add("uri", DekiScriptExpression.Constant(deki.UiUri.Uri.ToString())); siteFields.Add("id", DekiScriptExpression.Constant(instance.Id)); env.Add("site", siteFields); // add page fields DekiScriptMap pageFields = new DekiScriptMap(); pageFields.Add("title", DekiScriptExpression.Constant(page.Title.AsUserFriendlyName())); pageFields.Add("path", DekiScriptExpression.Constant(page.Title.AsPrefixedDbPath())); pageFields.Add("namespace", DekiScriptExpression.Constant(Title.NSToString(page.Title.Namespace))); pageFields.Add("id", DekiScriptExpression.Constant(page.ID.ToString())); pageFields.Add("uri", DekiScriptExpression.Constant(Utils.AsPublicUiUri(page.Title))); pageFields.Add("date", DekiScriptExpression.Constant(page.TimeStamp.ToString("R"))); pageFields.Add("language", DekiScriptExpression.Constant(string.IsNullOrEmpty(page.Language) ? null : page.Language)); env.Add("page", pageFields); // add user fields DekiScriptMap userFields = new DekiScriptMap(); if (deki.User != null) { UserBE user = deki.User; userFields.Add("id", DekiScriptExpression.Constant(user.ID.ToString())); userFields.Add("name", DekiScriptExpression.Constant(user.Name)); userFields.Add("uri", DekiScriptExpression.Constant(Utils.AsPublicUiUri(Title.FromDbPath(NS.USER, user.Name, null)))); userFields.Add("emailhash", DekiScriptExpression.Constant(StringUtil.ComputeHashString((user.Email ?? string.Empty).Trim().ToLowerInvariant(), Encoding.UTF8))); userFields.Add("anonymous", DekiScriptExpression.Constant(UserBL.IsAnonymous(user).ToString().ToLowerInvariant())); userFields.Add("language", DekiScriptExpression.Constant(string.IsNullOrEmpty(user.Language) ? null : user.Language)); } else { userFields.Add("id", DekiScriptExpression.Constant("0")); userFields.Add("name", DekiScriptExpression.Constant(string.Empty)); userFields.Add("uri", DekiScriptExpression.Constant(string.Empty)); userFields.Add("emailhash", DekiScriptExpression.Constant(string.Empty)); userFields.Add("anonymous", DekiScriptExpression.Constant("true")); userFields.Add("language", DekiScriptNil.Value); } env.Add("user", userFields); // store env for later current.SetState("pageimplicitenv-" + page.ID, env); } // set implicit environment DreamContext.Current.SetState(env); }
public virtual DekiScriptLiteral Evaluate(DekiScriptExpression expr, DekiScriptEvalMode mode, DekiScriptEnv env) { DekiScriptExpressionEvaluationState state = new DekiScriptExpressionEvaluationState(mode, env, this); try { return state.Pop(expr.VisitWith(DekiScriptExpressionEvaluation.Instance, state)); } catch(DekiScriptReturnException e) { state.Push(e.Value); return state.PopAll(); } }
void Unary(out DekiScriptExpression expr) { Stack<Tuplet<Location, DekiScriptUnary.Op>> stack = new Stack<Tuplet<Location, DekiScriptUnary.Op>>(); while (StartOf(8)) { if (la.kind == 56) { Get(); stack.Push(new Tuplet<Location, DekiScriptUnary.Op>(t.Location, DekiScriptUnary.Op.Negate)); } else if (la.kind == 55) { Get(); } else if (la.kind == 60) { Get(); stack.Push(new Tuplet<Location, DekiScriptUnary.Op>(t.Location, DekiScriptUnary.Op.LogicalNot)); } else if (la.kind == 61) { Get(); stack.Push(new Tuplet<Location, DekiScriptUnary.Op>(t.Location, DekiScriptUnary.Op.TypeOf)); } else { Get(); stack.Push(new Tuplet<Location, DekiScriptUnary.Op>(t.Location, DekiScriptUnary.Op.Length)); } } Primary(out expr); while(stack.Count > 0) { var item = stack.Pop(); expr = DekiScriptExpression.UnaryOp(item.Item1, item.Item2, expr); } }
void MulExpr(out DekiScriptExpression expr) { DekiScriptExpression inner = null; DekiScriptBinary.Op op = DekiScriptBinary.Op.LeftValue; Location location = Location.None; Unary(out expr); while (la.kind == 57 || la.kind == 58 || la.kind == 59) { if (la.kind == 57) { Get(); op = DekiScriptBinary.Op.Multiplication; } else if (la.kind == 58) { Get(); op = DekiScriptBinary.Op.Division; } else { Get(); op = DekiScriptBinary.Op.Modulo; } location = t.Location; Unary(out inner); expr = DekiScriptExpression.BinaryOp(location, op, expr, inner); } }
void AddExpr(out DekiScriptExpression expr) { DekiScriptExpression inner = null; DekiScriptBinary.Op op = DekiScriptBinary.Op.LeftValue; Location location = Location.None; MulExpr(out expr); while (la.kind == 55 || la.kind == 56) { if (la.kind == 55) { Get(); op = DekiScriptBinary.Op.Addition; } else { Get(); op = DekiScriptBinary.Op.Subtraction; } location = t.Location; MulExpr(out inner); expr = DekiScriptExpression.BinaryOp(location, op, expr, inner); } }
void ConcatExpr(out DekiScriptExpression expr) { DekiScriptExpression inner = null; Location location = Location.None; DekiScriptBinary.Op op = DekiScriptBinary.Op.LeftValue; AddExpr(out expr); while (la.kind == 53 || la.kind == 54) { if (la.kind == 53) { Get(); op = DekiScriptBinary.Op.Concat; } else { Get(); op = DekiScriptBinary.Op.UriAppend; } location = t.Location; AddExpr(out inner); expr = DekiScriptExpression.BinaryOp(location, op, expr, inner); } }
void RelExpr(out DekiScriptExpression expr) { DekiScriptExpression inner = null; DekiScriptBinary.Op op = DekiScriptBinary.Op.LeftValue; Location location = Location.None; bool negate = false; ConcatExpr(out expr); while (StartOf(6)) { if (StartOf(7)) { if (la.kind == 45) { Get(); op = DekiScriptBinary.Op.LessThan; } else if (la.kind == 46) { Get(); op = DekiScriptBinary.Op.GreaterThan; } else if (la.kind == 47) { Get(); op = DekiScriptBinary.Op.LessOrEqual; } else { Get(); op = DekiScriptBinary.Op.GreaterOrEqual; } location = t.Location; ConcatExpr(out inner); expr = DekiScriptExpression.BinaryOp(location, op, expr, inner); } else if (la.kind == 49) { Get(); location = t.Location; if (la.kind == 50) { Get(); negate = true; } if (la.kind == 51) { Get(); expr = DekiScriptExpression.BinaryOp(location, DekiScriptBinary.Op.IsType, expr, DekiScriptExpression.Constant("nil")); } else if (la.kind == 1) { Get(); expr = DekiScriptExpression.BinaryOp(location, DekiScriptBinary.Op.IsType, expr, DekiScriptExpression.Constant(t.val)); } else SynErr(82); } else { if (la.kind == 50) { Get(); negate = true; } Expect(52); location = t.Location; ConcatExpr(out inner); expr = DekiScriptExpression.BinaryOp(location, DekiScriptBinary.Op.InCollection, expr, inner); } if(negate) expr = DekiScriptExpression.UnaryOp(location, DekiScriptUnary.Op.LogicalNot, expr); } }
//--- Constructors --- public DekiScriptExpressionInvocationTarget(DreamAccess access, DekiScriptParameter[] parameters, DekiScriptExpression expr) : this(access, parameters, expr, null) { }
void Literal(out DekiScriptExpression expr) { expr = null; Location location = Location.None; switch (la.kind) { case 51: case 66: case 67: { Nil(out expr); break; } case 68: case 69: { Bool(out expr); break; } case 5: case 6: { Number(out expr); break; } case 3: case 4: { String(out expr); break; } case 7: { EntityString(out expr); break; } case 2: { MagicId(out expr); break; } case 9: { Map(out location, out expr); break; } case 64: { List(out expr); break; } case 45: { Xml(out expr); break; } default: SynErr(85); break; } }
void ArgList(out Location location, out DekiScriptExpression expr) { List<DekiScriptExpression> list = new List<DekiScriptExpression>(); location = Location.None; Expect(22); location = t.Location; if (StartOf(2)) { Expression(out expr); list.Add(expr); while (la.kind == 20) { Get(); Expression(out expr); list.Add(expr); } } Expect(23); expr = DekiScriptExpression.List(location, list); }
void Map(out Location location, out DekiScriptExpression expr) { List<DekiScriptMapConstructor.FieldConstructor> list = new List<DekiScriptMapConstructor.FieldConstructor>(); DekiScriptMapConstructor.FieldConstructor field = null; DekiScriptGenerator gen = null; location = Location.None; Expect(9); location = t.Location; if (StartOf(12)) { Field(out field); list.Add(field); while (la.kind == 20) { Get(); Field(out field); list.Add(field); } if (la.kind == 28) { Get(); GeneratorHead(out gen); } } Expect(10); expr = DekiScriptExpression.Map(location, gen, list.ToArray()); }
public void Execute(ExecutionPlan plan) { var service = DreamTestHelper.CreateService( _hostinfo, "sid://mindtouch.com/2007/12/dekiscript", "dekiscript", new XDoc("config").Elem("manifest", _manifestUri) ); foreach (var functionName in _manifest["function/name"]) { var name = functionName.AsText; _tester.Runtime.RegisterFunction(name, service.AtLocalHost.At(name)); } try { var expr = _tester.Parse(plan.Expr); var env = _tester.Runtime.CreateEnv(); env.Vars.Add(DekiScriptEnv.SAFEMODE, DekiScriptExpression.Constant(plan.Safe)); DekiScriptExpression result = _tester.Runtime.Evaluate(expr, plan.Safe ? DekiScriptEvalMode.EvaluateSafeMode : DekiScriptEvalMode.Evaluate, env); if (plan.TypedVerification != null) { Assert.AreEqual(plan.ExpectedType, result.GetType()); plan.TypedVerification(result); } else if (plan.DocVerification != null) { if (!(result is DekiScriptXml)) { Assert.Fail(string.Format("return type was '{0}' not DekiScriptXml", result.GetType())); } var doc = ((DekiScriptXml)result).Value; plan.DocVerification(doc); } else if (plan.StringVerification != null) { string value; if (result is DekiScriptString) { value = ((DekiScriptString)result).Value; } else if (result is DekiScriptXml) { value = ((DekiScriptXml)result).Value.ToString(); } else { value = result.ToString(); } plan.StringVerification(value, result.GetType()); } else { Assert.Fail("Execution completed without exception"); } } catch (Exception e) { if (plan.ExceptionVerification != null) { plan.ExceptionVerification(e); } else { throw; } } finally { service.WithPrivateKey().AtLocalHost.Delete(); } }
private void LoadScript() { _manifestPath = null; _resourcesPath = null; _manifestUri = null; _resourcesUri = null; _manifest = null; // read manifest _manifestPath = Config["manifest"].AsText; if (string.IsNullOrEmpty(_manifestPath)) { throw new ArgumentNullException("manifest"); } _manifestUri = XUri.TryParse(_manifestPath); if (_manifestUri != null) { _manifestPath = null; _manifest = Plug.New(_manifestUri).Get().ToDocument(); _resourcesUri = Config["resources"].AsUri ?? _manifestUri.WithoutLastSegment(); } else { _manifest = XDocFactory.LoadFrom(_manifestPath, MimeType.XML); _resourcesPath = Config["resources"].AsText ?? Path.GetDirectoryName(_manifestPath); } if (!_manifest.HasName("extension")) { throw new ArgumentException("invalid extension manifest"); } // initilize runtime _runtime = new DekiScriptRuntime(); // read manifest settings _title = _manifest["title"].AsText; _label = _manifest["label"].AsText; _copyright = _manifest["copyright"].AsText; _description = _manifest["description"].AsText; _help = _manifest["uri.help"].AsText; _logo = _manifest["uri.logo"].AsText; _namespace = _manifest["namespace"].AsText; // initialize evaluation environment _commonEnv = _runtime.CreateEnv(); // read functions _functions = new Dictionary <XUri, DekiScriptInvocationTargetDescriptor>(); foreach (var function in _manifest["function"]) { var descriptor = ConvertFunction(function); if (descriptor != null) { var uri = Self.At(descriptor.SystemName); DekiScriptInvocationTargetDescriptor old; if (_functions.TryGetValue(uri, out old)) { _log.WarnFormat("duplicate function name {0} in script {1}", descriptor.Name, _manifestUri); } _functions[uri] = descriptor; } } _runtime.RegisterExtensionFunctions(_functions); // add extension functions to env foreach (var function in _functions) { _commonEnv.Vars.AddNativeValueAt(function.Value.Name.ToLowerInvariant(), function.Key); } // add configuration settings DreamContext context = DreamContext.Current; DekiScriptMap scriptConfig = new DekiScriptMap(); foreach (KeyValuePair <string, string> entry in Config.ToKeyValuePairs()) { XUri local; if (XUri.TryParse(entry.Value, out local)) { local = context.AsPublicUri(local); scriptConfig.AddAt(entry.Key.Split('/'), DekiScriptExpression.Constant(local.ToString())); } else { scriptConfig.AddAt(entry.Key.Split('/'), DekiScriptExpression.Constant(entry.Value)); } } _commonEnv.Vars.Add("config", scriptConfig); }
//--- Extension Methods --- public static DekiScriptExpression Optimize(this DekiScriptRuntime runtime, DekiScriptExpression expr, DekiScriptEvalMode mode, DekiScriptEnv env) { return expr.VisitWith(DekiScriptExpressionOptimizer.Instance, new DekiScriptExpressionEvaluationState(mode, env, runtime)); }
private DekiScriptDomElement.Attribute Optimize(DekiScriptDomElement.Attribute expr, DekiScriptOptimizerState state) { DekiScriptExpression value = expr.Value.VisitWith(DekiScriptExpressionOptimizer.Instance, state); return(new DekiScriptDomElement.Attribute(expr.Location, expr.Prefix, expr.Name, value)); }
void Nil(out DekiScriptExpression expr) { if (la.kind == 66) { Get(); } else if (la.kind == 51) { Get(); } else if (la.kind == 67) { Get(); } else SynErr(87); expr = DekiScriptNil.Value; }
void TernaryExpression(out DekiScriptExpression expr) { DekiScriptExpression left = null, right = null; Location location = Location.None; NullCoalescingExpr(out expr); if (la.kind == 37) { Get(); location = t.Location; Expression(out left); Expect(31); Expression(out right); expr = DekiScriptExpression.TernaryOp(location, expr, left, right); } }
private DekiScriptInvocationTargetDescriptor ConvertFunction(XDoc function) { string functionName = function["name"].AsText; if (string.IsNullOrEmpty(functionName)) { _log.WarnFormat("function without name in script {0}; skipping function definition", _manifestUri); return(null); } // determine function access level DreamAccess access; switch (function["access"].AsText ?? "public") { case "private": access = DreamAccess.Private; break; case "internal": access = DreamAccess.Internal; break; case "public": access = DreamAccess.Public; break; default: _log.WarnFormat("unrecognized access level '{0}' for function {1} in script {2}; defaulting to public", function["access"].AsText, functionName, _manifestUri); access = DreamAccess.Public; break; } // convert parameters List <DekiScriptParameter> parameters = new List <DekiScriptParameter>(); foreach (XDoc param in function["param"]) { string paramName = param["@name"].AsText; // determine if parameter has a default value string paramDefault = param["@default"].AsText; DekiScriptLiteral paramDefaultExpression = DekiScriptNil.Value; bool paramOptional = false; if (paramDefault != null) { paramOptional = true; try { paramDefaultExpression = ScriptRuntime.Evaluate(DekiScriptParser.Parse(Location.Start, paramDefault), DekiScriptEvalMode.Evaluate, ScriptRuntime.CreateEnv()); } catch (Exception e) { _log.ErrorExceptionFormat(e, "invalid default value for parameter {0} in function {1} in script {2}; skipping function definition", paramName, functionName, _manifestUri); return(null); } } else { paramOptional = (param["@optional"].AsText == "true"); } // determine parameter type string paramType = param["@type"].AsText ?? "any"; DekiScriptType paramScriptType; if (!SysUtil.TryParseEnum(paramType, out paramScriptType)) { _log.WarnFormat("unrecognized param type '{0}' for parameter {1} in function {2} in script {3}; defaulting to any", paramType, paramName, functionName, _manifestUri); paramScriptType = DekiScriptType.ANY; } // add parameter parameters.Add(new DekiScriptParameter(paramName, paramScriptType, paramOptional, param.Contents, typeof(object), paramDefaultExpression)); } var parameterArray = parameters.ToArray(); // determine function body XDoc ret = function["return"]; string src = ret["@src"].AsText; string type = ret["@type"].AsText; DekiScriptExpression expression; if (!string.IsNullOrEmpty(src)) { // 'src' attribute is set, load the script from it XDoc script; if (_manifestUri != null) { // check if uri is relative XUri scriptUri = XUri.TryParse(src) ?? _manifestUri.AtPath(src); script = Plug.New(scriptUri).Get().ToDocument(); } else { // check if filename is relative if (!Path.IsPathRooted(src)) { src = Path.Combine(_resourcesPath, src); } script = XDocFactory.LoadFrom(src, MimeType.XML); } expression = DekiScriptParser.Parse(script); type = type ?? "xml"; } else if (!ret["html"].IsEmpty) { // <return> element contains a <html> node; parse it as a script expression = DekiScriptParser.Parse(ret["html"]); type = type ?? "xml"; } else if (!ret.IsEmpty) { // <return> element contains something else; use the text contents as deki-script expression var location = new Location(string.Format("/function[name={0}]/return", functionName)); expression = DekiScriptParser.Parse(location, function["return"].AsText ?? string.Empty); expression = DekiScriptExpression.ReturnScope(location, expression); type = type ?? "any"; } else { _log.WarnFormat("function {0} has no body in script {1}; skipping function definition", functionName, _manifestUri); return(null); } // determine return type DekiScriptType returnScriptType; if (!SysUtil.TryParseEnum(type, out returnScriptType)) { _log.WarnFormat("unrecognized return type '{0}' for function {1} in script {2}; defaulting to any", type, functionName, _manifestUri); returnScriptType = DekiScriptType.ANY; } // create function descriptor var target = new DekiScriptScriptFunctionInvocationTarget(access, parameterArray, expression, _commonEnv, returnScriptType); string description = function["description"].AsText; string transform = function["@transform"].AsText; return(new DekiScriptInvocationTargetDescriptor(access, false, false, functionName, parameterArray, returnScriptType, description, transform, target)); }
void Bool(out DekiScriptExpression expr) { expr = null; if (la.kind == 68) { Get(); expr = DekiScriptBool.True; } else if (la.kind == 69) { Get(); expr = DekiScriptBool.False; } else SynErr(88); }
public DekiScriptDom Visit(DekiScriptDomComment expr, DekiScriptOptimizerState state) { DekiScriptExpression value = expr.Value.VisitWith(DekiScriptExpressionOptimizer.Instance, state); return(new DekiScriptDomComment(expr.Location, value)); }
void Number(out DekiScriptExpression expr) { expr = null; if (la.kind == 5) { Get(); expr = DekiScriptExpression.Constant(SysUtil.ChangeType<double>(t.val)); } else if (la.kind == 6) { Get(); expr = DekiScriptExpression.Constant(long.Parse(t.val.Substring(2), System.Globalization.NumberStyles.AllowHexSpecifier)); } else SynErr(89); }
//--- Constructors --- internal DekiScriptTernary(DekiScriptExpression test, DekiScriptExpression left, DekiScriptExpression right, bool isIfElse) { this.Test = test; this.Left = left; this.Right = right; IsIfElse = isIfElse; }
void String(out DekiScriptExpression expr) { string value = null; bool block; AnyString(out value, out block); expr = DekiScriptExpression.Constant(value); }
public void OutputBuffer_web_uri_followed_by_html() { var expr = DekiScriptExpression.Block(Location.None, new[] { DekiScriptExpression.Constant(new XUri("http://foo/index.html")), DekiScriptExpression.Constant(new XDoc("html").Elem("body", "test")) }); _dekiScriptTester.Test( expr, @"<html><body><a rel=""custom nofollow"" href=""http://foo/index.html"">http://foo/index.html</a>test</body></html>", typeof(DekiScriptXml), false ); }
void EntityString(out DekiScriptExpression expr) { string value = null; Expect(7); expr = DekiScriptExpression.Constant(StringUtil.DecodeHtmlEntities(t.val)); }
public void OutputBuffer_web_uri_inside_xml() { var expr = DekiScriptExpression.XmlElement(Location.None, null, DekiScriptExpression.Constant("doc"), null, DekiScriptExpression.Constant(new XUri("http://foo/index.html"))); _dekiScriptTester.Test( expr, @"<doc><a rel=""custom nofollow"" href=""http://foo/index.html"">http://foo/index.html</a></doc>", typeof(DekiScriptXml), false ); }
void MagicId(out DekiScriptExpression expr) { Location location = t.Location; Expect(2); expr = DekiScriptExpression.MagicId(location, t.val.Substring(1)); }
public static DekiScriptEnv CreateEnvironment(PageBE page) { DekiScriptEnv commonEnv = DekiContext.Current.Instance.CreateEnvironment(); // need to strip the config value back out for Deki commonEnv.Vars["config"] = new DekiScriptMap(); // initialize environment DekiScriptEnv env = commonEnv; DekiContext deki = DekiContext.Current; DekiInstance instance = deki.Instance; // add site variables env.Vars.AddNativeValueAt("site.name", instance.SiteName); env.Vars.AddNativeValueAt("site.hostname", deki.UiUri.Uri.HostPort); env.Vars.AddNativeValueAt("site.api", deki.ApiUri.SchemeHostPortPath); env.Vars.AddNativeValueAt("site.language", instance.SiteLanguage); env.Vars.AddNativeValueAt("site.uri", deki.UiUri.Uri.ToString()); env.Vars.AddNativeValueAt("site.pagecount", deki.Deki.PropertyAt("$sitepagecount")); env.Vars.AddNativeValueAt("site.usercount", deki.Deki.PropertyAt("$siteusercount")); env.Vars.AddNativeValueAt("site.homepage", deki.Deki.PropertyAt("$page", DekiContext.Current.Instance.HomePageId, true)); env.Vars.AddNativeValueAt("site.feed", deki.ApiUri.At("site", "feed").ToString()); env.Vars.AddNativeValueAt("site.tags", deki.Deki.PropertyAt("$sitetags")); env.Vars.AddNativeValueAt("site.users", deki.Deki.PropertyAt("$siteusers")); env.Vars.AddNativeValueAt("site.id", DekiScriptExpression.Constant(instance.Id)); env.Vars.AddNativeValueAt("site.timezone", DekiScriptExpression.Constant(instance.SiteTimezone)); // add page variables env.Vars.Add("page", deki.Deki.PropertyAt("$page", page.ID, true)); // add user variables env.Vars.Add("user", deki.Deki.PropertyAt("$user", (deki.User != null) ? deki.User.ID : 0)); // add instance functions & properties bool hasUnsafeContentPermission = DekiXmlParser.PageAuthorCanExecute(); foreach (var service in instance.RunningServices.ExtensionServices) { if (service != null) { var extension = service.Extension; if (extension != null) { if (hasUnsafeContentPermission || !extension.IsProtected) { var functions = extension.Functions; if (functions != null) { foreach (var function in functions) { env.Vars.AddNativeValueAt(function.Name.ToLowerInvariant(), function.Uri); } } else { _log.WarnFormat("CreateEnvironment - null functions (id: {0})", service.ServiceId); } } } else { _log.WarnFormat("CreateEnvironment - null extension (id: {0})", service.ServiceId); } } else { _log.Warn("CreateEnvironment - null service"); } } return(env); }
private void BuildElement(XmlNode current, ICollection <DekiScriptExpression> list) { // create new element var attributes = BuildAttributes(current); var elem = DekiScriptExpression.XmlElement(Location, current.Prefix, DekiScriptExpression.Constant(current.LocalName), attributes.ToArray(), BuildChildren(current)); list.Add(elem); }
public Hashtable PopularPages( [DekiExtParam("max results (default: 10)", true)] int?max, [DekiExtParam("poll interval (only for js format, default: 30)", true)] int?interval ) { int maxResults = max ?? 10; int resultCount = 0; DekiScriptMap env = DreamContext.Current.GetState <DekiScriptMap>(); DekiScriptLiteral uriLiteral = env.GetAt("site.uri"); XUri deki = new XUri(uriLiteral.NativeValue.ToString()).At("@api", "deki"); Hashtable map = new Hashtable(StringComparer.OrdinalIgnoreCase); map.Add("interval", _ttl.TotalSeconds); ArrayList pages = new ArrayList(); map.Add("pages", pages); int total = 0; Dictionary <uint, int> rankLookup = new Dictionary <uint, int>(); lock (_pageViews) { foreach (View view in _pageViews) { if (rankLookup.ContainsKey(view.PageId)) { rankLookup[view.PageId]++; } else { rankLookup[view.PageId] = 1; } total++; } } List <Tuplet <uint, int> > rank = new List <Tuplet <uint, int> >(); foreach (KeyValuePair <uint, int> kvp in rankLookup) { rank.Add(new Tuplet <uint, int>(kvp.Key, kvp.Value)); } rank.Sort(delegate(Tuplet <uint, int> a, Tuplet <uint, int> b) { return(b.Item2.CompareTo(a.Item2)); }); map.Add("total", total); foreach (Tuplet <uint, int> page in rank) { Hashtable pageMap = new Hashtable(StringComparer.OrdinalIgnoreCase); pages.Add(pageMap); // BUGBUGBUG (arnec): the AsLocalUri should not be required after bug #5964 is resolved pageMap.Add("page", DekiScriptExpression.Constant(deki.At("$page").AsLocalUri(), new[] { DekiScriptExpression.Constant(page.Item1), DekiScriptExpression.Constant(true) })); pageMap.Add("views", page.Item2); resultCount++; if (resultCount >= maxResults) { break; } } return(map); }
private List <DekiScriptXmlElement.Attribute> BuildAttributes(XmlNode current) { List <DekiScriptXmlElement.Attribute> result = new List <DekiScriptXmlElement.Attribute>(current.Attributes.Count); for (int i = 0; i < current.Attributes.Count; ++i) { XmlAttribute attribute = current.Attributes[i]; PushNode(attribute); // check if attribute needs to be evaluated if (attribute.NamespaceURI == XDekiScript.ScriptNS) { // NOTE (steveb): eval:key="value" DekiScriptXmlElement.Attribute attr = new DekiScriptXmlElement.Attribute(Location, null, DekiScriptExpression.Constant(attribute.LocalName), Parse(Location, attribute.Value)); result.Add(attr); } else if (attribute.Value.StartsWithInvariant("{{") && attribute.Value.EndsWithInvariant("}}")) { // NOTE (steveb): key="{{value}}" DekiScriptExpression expr = Parse(Location, StripCode(attribute.Value.Substring(2, attribute.Value.Length - 4))); DekiScriptXmlElement.Attribute attr = new DekiScriptXmlElement.Attribute(Location, attribute.Prefix, DekiScriptExpression.Constant(attribute.LocalName), expr); result.Add(attr); } else if (!attribute.NamespaceURI.EqualsInvariant("http://www.w3.org/2000/xmlns/") || !attribute.Value.EqualsInvariant("http://mindtouch.com/2007/dekiscript")) { // skip "init", "if", "foreach", "block", "where", "function" since they have already been processed if (!attribute.NamespaceURI.EqualsInvariant(string.Empty) || !( attribute.LocalName.EqualsInvariant("init") || attribute.LocalName.EqualsInvariant("if") || attribute.LocalName.EqualsInvariant("foreach") || attribute.LocalName.EqualsInvariant("where") || attribute.LocalName.EqualsInvariant("block") || attribute.LocalName.EqualsInvariant("function") )) { // add static attribute DekiScriptXmlElement.Attribute attr = new DekiScriptXmlElement.Attribute(Location, attribute.Prefix, DekiScriptExpression.Constant(attribute.LocalName), DekiScriptExpression.Constant(attribute.Value)); result.Add(attr); } } PopNode(); } return(result); }
public DekiScriptExpressionInvocationTarget(DreamAccess access, DekiScriptParameter[] parameters, DekiScriptExpression expr, DekiScriptEnv env) { if (parameters == null) { throw new ArgumentNullException("parameters"); } if (expr == null) { throw new ArgumentNullException("expr"); } this.Access = access; this.Parameters = parameters; this.Expression = expr; _env = env; }
private DekiScriptExpression Html(string container, string tag, string type, DekiScriptExpression expr) { DekiScriptExpression style = DekiScriptExpression.XmlElement(Location, null, DekiScriptExpression.Constant(tag), new[] { new DekiScriptXmlElement.Attribute(Location, null, DekiScriptExpression.Constant("type"), DekiScriptExpression.Constant(type)) }, expr); DekiScriptExpression head = DekiScriptExpression.XmlElement(Location, null, DekiScriptExpression.Constant(container), null, style); DekiScriptExpression html = DekiScriptExpression.XmlElement(Location, null, DekiScriptExpression.Constant("html"), null, head); return(html); }
private void Test(string expression) { DekiScriptExpression expr = DekiScriptParser.Parse(Location.Start, expression); Assert.AreEqual(expression, expr.ToString()); }
private DekiScriptExpression TryCatch(DekiScriptExpression expr, bool scripted) { if(scripted) { var handler = DekiScriptExpression.Call(Location, DekiScriptExpression.Access(Location, DekiScriptExpression.Id(Location, "web"), DekiScriptExpression.Constant("showerror")), DekiScriptExpression.List(Location, new[] {DekiScriptExpression.Id(Location, "__error")})); return DekiScriptExpression.Block(Location, DekiScriptExpression.TryCatchFinally(Location, expr, handler, DekiScriptNil.Value)); } return expr; }
//--- Extension Methods --- public static DekiScriptExpression Optimize(this DekiScriptRuntime runtime, DekiScriptExpression expr, DekiScriptEvalMode mode, DekiScriptEnv env) { return(expr.VisitWith(DekiScriptExpressionOptimizer.Instance, new DekiScriptExpressionEvaluationState(mode, env, runtime, TimeSpan.MaxValue, int.MaxValue))); }
private void AddXDoc(XmlNode contextualbody, XDoc doc) { // check if this is a no-op if (doc.IsEmpty) { return; } // create a sub-buffer for processing DekiScriptOutputBuffer buffer = new DekiScriptOutputBuffer(int.MaxValue); // push all nodes from the XML document into the buffer Stack <XmlNode> stack = new Stack <XmlNode>(); // check if we're dealing with a simple <html><body> ... </body></html> document bool addSiblings = false; if ((doc.AsXmlNode.NodeType == XmlNodeType.Element) && doc.HasName("html") && doc["head/*"].IsEmpty && doc["tail/*"].IsEmpty && doc["body[@target]"].IsEmpty) { var body = doc["body"]; if (body.IsEmpty || (body.AsXmlNode.ChildNodes.Count == 0)) { // nothing to do return; } doc = doc[body.AsXmlNode.FirstChild]; addSiblings = true; } // loop over nodes XmlNode current = doc.AsXmlNode; do { XmlElement element; switch (current.NodeType) { case XmlNodeType.Element: element = (XmlElement)current; AppendXmlStart(buffer, element); if (element.HasChildNodes) { stack.Push(addSiblings || (stack.Count > 0) ? current.NextSibling : null); current = element.FirstChild; continue; } buffer.PushXmlEnd(); break; case XmlNodeType.Attribute: buffer.Push(DekiScriptExpression.Constant((string.IsNullOrEmpty(current.Prefix) ? current.Name : current.Prefix + ":" + current.Name) + "=" + current.Value.QuoteString())); break; case XmlNodeType.CDATA: case XmlNodeType.SignificantWhitespace: case XmlNodeType.Text: case XmlNodeType.Whitespace: buffer.Push(DekiScriptExpression.Constant(current.Value)); break; default: // ignore this node break; } // move onto next item or resume previous one current = addSiblings || (stack.Count > 0) ? current.NextSibling : null; while ((current == null) && (stack.Count > 0)) { buffer.PushXmlEnd(); current = stack.Pop(); } } while(current != null); // parse the sub-buffer ParseBuffer(buffer, 0, contextualbody, false); }
//--- Class Methods --- public static XmlNode Evaluate( XDoc script, XmlElement node, DekiScriptEvalContext context, DekiScriptEnv env, DekiScriptRuntime runtime, out bool scripted, ref bool error ) { if ((context.Mode != DekiScriptEvalMode.Verify) && (context.Mode != DekiScriptEvalMode.EvaluateEditOnly) && (context.Mode != DekiScriptEvalMode.EvaluateSaveOnly)) { throw new InvalidOperationException("DekiScript interpreter can only used for save, edit, or verify evaluations."); } scripted = false; XmlNode next = node.NextSibling; try { // check if element needs to be evaluated if (StringUtil.EqualsInvariant(node.NamespaceURI, XDekiScript.ScriptNS)) { scripted = true; // NOTE (steveb): <eval:xyz> nodes are not processed by the interpreter anymore } else { XDoc current = script[node]; bool hasScriptClass = StringUtil.EqualsInvariant(node.GetAttribute("class"), "script"); #region <elem class="script" init="..." if="..." foreach="..." where="..." block="..."> // check if element has form <elem class="script" init="..." if="..." foreach="..." where="..." block="..."> scripted = node.HasAttribute("init") || node.HasAttribute("if") || node.HasAttribute("foreach") || node.HasAttribute("block"); if (context.Mode == DekiScriptEvalMode.Verify) { // check if "block" is present string blockAttr = node.GetAttribute("block"); if (!string.IsNullOrEmpty(blockAttr)) { // TODO (steveb): validate script expression } // check if "foreach" is present string foreachAttr = node.GetAttribute("foreach"); if (!string.IsNullOrEmpty(foreachAttr)) { // TODO (steveb): validate script expression } // check if "if" is present string ifAttr = node.GetAttribute("if"); if (!string.IsNullOrEmpty(ifAttr)) { // TODO (steveb): validate script expression } // check if "init" is present string initAttr = node.GetAttribute("init"); if (!string.IsNullOrEmpty(initAttr)) { // TODO (steveb): validate script expression } } #endregion // evaluate child nodes EvaluateChildren(script, node, context, env, runtime, out scripted, ref error); #region evaluate attributes for (int i = 0; i < node.Attributes.Count; ++i) { XmlAttribute attribute = node.Attributes[i]; // check if attribute needs to be evaluated if (attribute.NamespaceURI == XDekiScript.ScriptNS) { scripted = true; // NOTE (steveb): eval:xyz="abc" attributes are not processed by the interpreter anymore } else if (StringUtil.StartsWithInvariant(attribute.Value, "{{") && StringUtil.EndsWithInvariant(attribute.Value, "}}")) { scripted = true; // NOTE (steveb): key="{{value}}" string code = attribute.Value.Substring(2, attribute.Value.Length - 4).Trim(); // check if script content is substituted bool isPermanentReplacement = false; if (StringUtil.StartsWithInvariantIgnoreCase(code, DekiScriptRuntime.ON_SAVE_PATTERN)) { isPermanentReplacement = (context.Mode == DekiScriptEvalMode.EvaluateSaveOnly); code = code.Substring(DekiScriptRuntime.ON_SAVE_PATTERN.Length); } else if (StringUtil.StartsWithInvariantIgnoreCase(code, DekiScriptRuntime.ON_SUBST_PATTERN)) { isPermanentReplacement = (context.Mode == DekiScriptEvalMode.EvaluateSaveOnly); code = code.Substring(DekiScriptRuntime.ON_SUBST_PATTERN.Length); } else if (StringUtil.StartsWithInvariantIgnoreCase(code, DekiScriptRuntime.ON_EDIT_PATTERN)) { isPermanentReplacement = (context.Mode == DekiScriptEvalMode.EvaluateEditOnly); code = code.Substring(DekiScriptRuntime.ON_EDIT_PATTERN.Length); } // parse expression if ((context.Mode == DekiScriptEvalMode.Verify) || isPermanentReplacement) { DekiScriptExpression expression = DekiScriptParser.Parse(ComputeNodeLocation(attribute), code); if (isPermanentReplacement) { DekiScriptLiteral eval = runtime.Evaluate(expression, DekiScriptEvalMode.EvaluateSafeMode, env); // determine what the outcome value is string value = eval.AsString(); // check if we have a value to replace the current attribute with if ((value != null) && !DekiScriptLibrary.ContainsXSSVulnerability(attribute.LocalName, value)) { attribute.Value = value; } else { node.Attributes.RemoveAt(i); --i; } } } } } #endregion #region evaluate <span class="script"> or <pre class="script"> if (hasScriptClass && (StringUtil.EqualsInvariant(node.LocalName, "pre") || StringUtil.EqualsInvariant(node.LocalName, "span")) && !node.HasAttribute("function")) { // replace the non-breaking space character with space string code = node.InnerText.ReplaceAll("\u00A0", " ", "\u00AD", "").Trim(); // check if script content is substituted bool isPermanentReplacement = false; if (StringUtil.StartsWithInvariantIgnoreCase(code, DekiScriptRuntime.ON_SAVE_PATTERN)) { isPermanentReplacement = (context.Mode == DekiScriptEvalMode.EvaluateSaveOnly); code = code.Substring(DekiScriptRuntime.ON_SAVE_PATTERN.Length); } else if (StringUtil.StartsWithInvariantIgnoreCase(code, DekiScriptRuntime.ON_SUBST_PATTERN)) { isPermanentReplacement = (context.Mode == DekiScriptEvalMode.EvaluateSaveOnly); code = code.Substring(DekiScriptRuntime.ON_SUBST_PATTERN.Length); } else if (StringUtil.StartsWithInvariantIgnoreCase(code, DekiScriptRuntime.ON_EDIT_PATTERN)) { isPermanentReplacement = (context.Mode == DekiScriptEvalMode.EvaluateEditOnly); code = code.Substring(DekiScriptRuntime.ON_EDIT_PATTERN.Length); } // parse expression if ((context.Mode == DekiScriptEvalMode.Verify) || isPermanentReplacement) { DekiScriptExpression expression = DekiScriptParser.Parse(ComputeNodeLocation(node), code); if (isPermanentReplacement) { DekiScriptLiteral value = runtime.Evaluate(expression, DekiScriptEvalMode.EvaluateSafeMode, env); context.ReplaceNodeWithValue(node, value); } if (!isPermanentReplacement) { scripted = true; } } } #endregion } } catch (Exception e) { // only embed error in verify mode, not in save/edit modes if (context.Mode == DekiScriptEvalMode.Verify) { context.InsertExceptionMessageBeforeNode(env, node.ParentNode, node, ComputeNodeLocation(node), e); node.ParentNode.RemoveChild(node); } error |= true; } return(next); }
protected override Yield Start(XDoc config, Result result) { yield return(Coroutine.Invoke(base.Start, config, new Result())); // loop over all resources Type type = GetType(); string assembly = type.Assembly.FullName.Split(new char[] { ',' }, 2)[0]; foreach (DekiExtLibraryFilesAttribute files in Attribute.GetCustomAttributes(type, typeof(DekiExtLibraryFilesAttribute))) { string prefix = files.Prefix ?? type.Namespace; foreach (string filename in files.Filenames) { MimeType mime = MimeType.FromFileExtension(filename); _files[filename] = Plug.New(string.Format("resource://{0}/{1}.{2}", assembly, prefix, filename)).With("dream.out.type", mime.FullType); } } // check if a public digital signature key was provided string dsaKey = config["deki-signature"].AsText ?? config["dekiwiki-signature"].AsText; if (dsaKey != null) { try { DSACryptoServiceProvider dsa = new DSACryptoServiceProvider(); dsa.ImportCspBlob(Convert.FromBase64String(dsaKey)); _publicDigitalSignature = dsa; } catch { throw new ArgumentException("invalid digital signature provided", "deki-signature"); } } // loop over all instance methods foreach (MethodInfo method in type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { // check if it has the DekiExtFunction attriute DekiExtFunctionAttribute ext = (DekiExtFunctionAttribute)Attribute.GetCustomAttribute(method, typeof(DekiExtFunctionAttribute)); if (ext != null) { // check if function has an associated script XDekiScript script = null; DekiExtFunctionScriptAttribute scriptAttr = (DekiExtFunctionScriptAttribute)Attribute.GetCustomAttribute(method, typeof(DekiExtFunctionScriptAttribute)); if (scriptAttr != null) { DreamMessage scriptresource = Plug.New(string.Format("resource://{0}/{1}.{2}", assembly, scriptAttr.Prefix ?? type.Namespace, scriptAttr.Scriptname)).With("dream.out.type", MimeType.XML.FullType).GetAsync().Wait(); if (scriptresource.IsSuccessful) { script = new XDekiScript(scriptresource.ToDocument()); } if (script == null) { throw new InvalidOperationException(string.Format("method '{0}' is declard as script, but script could not be loaded", method.Name)); } } // add function Add(ext, method, script); } } // add configuration settings var context = DreamContext.Current; _scriptConfig = new DekiScriptMap(); foreach (KeyValuePair <string, string> entry in Config.ToKeyValuePairs()) { XUri local; if (XUri.TryParse(entry.Value, out local)) { local = context.AsPublicUri(local); _scriptConfig.AddAt(entry.Key.Split('/'), DekiScriptExpression.Constant(local.ToString())); } else { _scriptConfig.AddAt(entry.Key.Split('/'), DekiScriptExpression.Constant(entry.Value)); } } result.Return(); }
void DefineConstruct(out DekiScriptExpression expr) { expr = null; DekiScriptExpression var; Location location = Location.None; AssignLHS(out var); if (la.kind == 12) { Get(); location = t.Location; Expression(out expr); expr = DekiScriptExpression.VarStatement(location, var, expr); } else if (StartOf(4)) { expr = DekiScriptExpression.VarStatement(location, var, DekiScriptNil.Value); } else SynErr(79); }