public void SafeXhtml_cleanses_Audio_src_attribute() { XDoc doc = XDocFactory.From("<doc><audio src=\"javascript://\" poster=\"javascript://\" autoplay=\"\" loop=\"\" controls=\"\"></audio></doc>", MimeType.TEXT_XML); DekiScriptLibrary.ValidateXHtml(doc, true, true); Assert.AreEqual("<doc><audio autoplay=\"\" loop=\"\" controls=\"\"></audio></doc>", doc.ToString()); }
public void UnSafeXhtml_cleanses_Audio_element() { XDoc doc = XDocFactory.From("<doc><audio src=\"\" poster=\"\" onloadstart=\"\" onprogress=\"\" unsafe=\"\"></audio></doc>", MimeType.TEXT_XML); DekiScriptLibrary.ValidateXHtml(doc, false, true); Assert.AreEqual("<doc><audio src=\"\" onloadstart=\"\" onprogress=\"\"></audio></doc>", doc.ToString()); }
public void SafeXhtml_cleanses_Video_element() { XDoc doc = XDocFactory.From("<doc><video src=\"\" poster=\"\" autoplay=\"\" loop=\"\" controls=\"\" width=\"\" height=\"\" onloadstart=\"\" onprogress=\"\"></video></doc>", MimeType.TEXT_XML); DekiScriptLibrary.ValidateXHtml(doc, true, true); Assert.AreEqual("<doc><video src=\"\" poster=\"\" autoplay=\"\" loop=\"\" controls=\"\" width=\"\" height=\"\"></video></doc>", doc.ToString()); }
public void UnSafeXhtml_cleanses_Video_with_sources() { XDoc doc = XDocFactory.From("<doc><video poster=\"\" onloadstart=\"\" onprogress=\"\"><source src=\"\" unsafe=\"\"/></video></doc>", MimeType.TEXT_XML); DekiScriptLibrary.ValidateXHtml(doc, false, true); Assert.AreEqual("<doc><video poster=\"\" onloadstart=\"\" onprogress=\"\"><source src=\"\" /></video></doc>", doc.ToString()); }
public XDoc WebXml( [DekiExtParam("XML source text or source uri")] string source, [DekiExtParam("xpath to value (default: none)", true)] string xpath, [DekiExtParam("namespaces (default: none)300+", true)] Hashtable namespaces, [DekiExtParam("caching duration in seconds (range: 300+; default: 300)", true)] double?ttl, [DekiExtParam("return nil if source could not be loaded (default: text with error message)", true)] bool?nilIfMissing ) { string text = WebText(source, xpath, namespaces, true, ttl, nilIfMissing); if (text == null) { return(null); } XDoc result = XDocFactory.From(text, MimeType.XML); if (result.IsEmpty) { // try again assuming the input is HTML if (text.TrimStart().StartsWith("<")) { result = XDocFactory.From(text, MimeType.HTML); } else { // wrap response into a valid HTML document result = new XDoc("html").Elem("body", text); } } if (result.HasName("html")) { result = DekiScriptLibrary.CleanseHtmlDocument(result); } return(result); }
public DekiScriptOutputBuffer.Range Visit(DekiScriptTryCatchFinally expr, DekiScriptExpressionEvaluationState state) { int marker = state.Buffer.Marker; try { expr.Try.VisitWith(this, state); } catch (DekiScriptFatalException) { throw; } catch (DekiScriptControlFlowException) { throw; } catch (Exception e) { state.Buffer.Reset(marker); // translate exception to an error object DekiScriptMap error = DekiScriptLibrary.MakeErrorObject(e, state.Env); // capture error object in a nested environment try { state.Env.Vars.Add(expr.Variable, error); expr.Catch.VisitWith(this, state); } finally { state.Env.Vars.Add(expr.Variable, DekiScriptNil.Value); } } finally { expr.Finally.VisitWith(this, state); } return(state.Buffer.Since(marker)); }
public XDoc External( [DekiExtParam("link")] string link ) { // store the original link value string originalLink = link; // remove spaces from the link link = link.Trim(); // extract the title if there is one (indicated by the first space) string title = String.Empty; int titleIndex = link.IndexOf(' '); if (0 < titleIndex) { title = link.Substring(titleIndex + 1, link.Length - titleIndex - 1); link = link.Substring(0, titleIndex); } // if the url is valid return it as a link - otherwise return the original text XDoc result = new XDoc("html").Start("body"); XUri uri = null; if (XUri.TryParse(link, out uri)) { result.Start("a").Attr("href", link).AddNodes(DekiScriptLibrary.WebHtml(title, null, null, null)["body"]).End(); } else { result.AddNodes(DekiScriptLibrary.WebHtml("[" + originalLink + "]", null, null, null)["body"]); } result.End(); return(result); }
public void CultureDateTime_with_utc_flagless_signature_assumes_utc_if_no_tz_specified() { double offset; var time = DekiScriptLibrary.CultureDateTimeParse("12:00pm", CultureInfo.InvariantCulture, out offset); Assert.AreEqual(DateTimeKind.Utc, time.Kind); Assert.AreEqual(12, time.Hour); Assert.AreEqual(0d, offset); }
public XDoc QueryLink( [DekiExtParam("query expression to link to")] string query, [DekiExtParam("link contents; can be text, an image, or another document (default: link uri)", true)] object text, [DekiExtParam("link hover title (default: link title)", true)] string title, [DekiExtParam("link target (default: nil)", true)] string target ) { return(DekiScriptLibrary.WebLink(_server.At("issues").With("q", query).ToString(), text, title, target)); }
public XDoc IssueLink( [DekiExtParam("YouTrack ID to link to (default: all issues)")] string id, [DekiExtParam("link contents; can be text, an image, or another document (default: link uri)", true)] object text, [DekiExtParam("link hover title (default: link title)", true)] string title, [DekiExtParam("link target (default: nil)", true)] string target ) { return(DekiScriptLibrary.WebLink(_server.At("issue", id).ToString(), text, title, target)); }
public void CultureDateTime_adjusts_kind_and_time_to_utc_if_tz_specified_and_utc_flag_is_false() { double offset; var time = DekiScriptLibrary.CultureDateTimeParse("12:00pm -03:00", CultureInfo.InvariantCulture, false, out offset); Assert.AreEqual(DateTimeKind.Utc, time.Kind); Assert.AreEqual(15, time.Hour); Assert.AreEqual(-3d, offset); }
public void CultureDateTime_does_not_adjust_kind_if_no_tz_specified_and_utc_flag_is_false() { double offset; var time = DekiScriptLibrary.CultureDateTimeParse("12:00pm", CultureInfo.InvariantCulture, false, out offset); Assert.AreEqual(DateTimeKind.Unspecified, time.Kind); Assert.AreEqual(12, time.Hour); Assert.AreEqual(0, offset); }
public void CultureDateTime_with_utc_flagless_signature_adjust_time_to_utc() { double offset; var time = DekiScriptLibrary.CultureDateTimeParse("12:00pm -03:00", CultureInfo.InvariantCulture, out offset); Assert.AreEqual(DateTimeKind.Utc, time.Kind); Assert.AreEqual(15, time.Hour); Assert.AreEqual(-3d, offset); }
public DekiScriptDom Visit(DekiScriptDomJson expr, DekiScriptOptimizerState state) { DekiScriptExpression value = expr.Value.VisitWith(DekiScriptExpressionOptimizer.Instance, state); if (value is DekiScriptLiteral) { return(new DekiScriptDomText(expr.Location, DekiScriptLibrary.JsonEmit(((DekiScriptLiteral)value).NativeValue))); } return(new DekiScriptDomJson(expr.Location, value)); }
internal DekiScriptXml(XDoc value, bool safe) { if (value == null) { throw new ArgumentNullException("value"); } if (safe) { value = DekiScriptLibrary.CleanseHtmlDocument(value); } this.Value = value; }
//--- Class Methods --- private static string ConvertDate(XDoc date) { long?epoch = date.AsLong; if (!epoch.HasValue) { return(null); } var datetime = DateTimeUtil.FromEpoch((uint)(epoch.Value / 1000)); return(DekiScriptLibrary.CultureDateTime(datetime)); }
public XDoc WebHtml( [DekiExtParam("HTML source text or source uri (default: none)", true)] string source, [DekiExtParam("xpath to value (default: none)", true)] string xpath, [DekiExtParam("namespaces (default: none)", true)] Hashtable namespaces, [DekiExtParam("caching duration in seconds (range: 300+; default: 300)", true)] double?ttl, [DekiExtParam("return nil if source could not be loaded (default: text with error message)", true)] bool?nilIfMissing ) { string text = WebText(source, xpath, namespaces, true, ttl, nilIfMissing); if (text == null) { return(null); } // convert text to html XDoc result = XDoc.Empty; using (TextReader reader = new StringReader("<html><body>" + text + "</body></html>")) { // NOTE (steveb): we create the sgml reader explicitly since we don't want a DTD to be associated with it; the DTD would force a potentially unwanted HTML structure // check if HTML entities DTD has already been loaded if (_htmlEntitiesDtd == null) { using (StreamReader dtdReader = new StreamReader(Plug.New("resource://mindtouch.deki.script/MindTouch.Deki.Script.HtmlEntities.dtd").Get().AsStream())) { _htmlEntitiesDtd = Sgml.SgmlDtd.Parse(null, "HTML", dtdReader, null, null, XDoc.XmlNameTable); } } Sgml.SgmlReader sgmlReader = new Sgml.SgmlReader(XDoc.XmlNameTable); sgmlReader.Dtd = _htmlEntitiesDtd; sgmlReader.DocType = "HTML"; sgmlReader.WhitespaceHandling = WhitespaceHandling.All; sgmlReader.CaseFolding = Sgml.CaseFolding.ToLower; sgmlReader.InputStream = reader; try { XmlDocument doc = new XmlDocument(XDoc.XmlNameTable); doc.PreserveWhitespace = true; doc.XmlResolver = null; doc.Load(sgmlReader); // check if a valid document was created if (doc.DocumentElement != null) { result = new XDoc(doc); } } catch (Exception) { // swallow parsing exceptions } } return(DekiScriptLibrary.CleanseHtmlDocument(result)); }
public void Can_execute_function_with_a_defaulted_param() { string path = LoadExtension(); DreamMessage result = Plug.New(_host.LocalMachineUri).At(path, "DefaultedParam").Post(new DekiScriptMap().ToXml()); Assert.IsTrue(result.IsSuccessful); XDoc resultDoc = result.ToDocument(); Assert.AreEqual("value", resultDoc.Name); Assert.AreEqual( "args.date: " + DekiScriptLibrary.DateNow().Substring(0, 4), resultDoc.Elements.First.AsText.Substring(0, 15)); }
public override XDoc AsEmbeddableXml(bool safe) { MimeType mime = (Value.Segments.Length > 0) ? MimeType.FromFileExtension(Value.LastSegment ?? string.Empty) : MimeType.BINARY; if (StringUtil.EqualsInvariant(mime.MainType, "image")) { // embed <img> tag return(DekiScriptLibrary.WebImage(AsString(), null, null, null)); } else { // embed <a> tag return(DekiScriptLibrary.WebLink(AsString(), null, null, null)); } }
public Empty Visit(DekiScriptDomJson expr, DekiScriptDomEvaluationState state) { var context = state.Context; var env = state.Env; var parent = state.Parent; try { DekiScriptLiteral value = expr.Value.VisitWith(DekiScriptExpressionEvaluation.Instance, env); XmlText result = context.CreateTextNode(DekiScriptLibrary.JsonEmit(value.NativeValue)); parent.AppendChild(result); } catch (Exception e) { EmbedExceptionMessage(expr, env, context, e, parent); } return(Empty.Value); }
public override XDoc AsEmbeddableXml(bool safe) { XDoc result = Value; if (!Value.IsEmpty && !Value.HasName("html")) { result = new XDoc("html").Start("body").Add(Value).End(); if (safe) { foreach (XDoc body in result["body"]) { DekiScriptLibrary.ValidateXHtml(body, true, true); } } } return(result); }
public void ThrowIfTimedout() { if (_sharedState.EvaluationTimer == null) { return; } if (_sharedState.EvaluationTimer.Elapsed <= _sharedState.EvaluationTimeout) { return; } _sharedState.EvaluationTimer.Stop(); var e = new TimeoutException("script execution has timed out"); var error = DekiScriptLibrary.MakeErrorObject(e, Env); _sharedState.EvaluationError = new DekiScriptXml(DekiScriptLibrary.WebShowError((Hashtable)error.NativeValue)); throw e; }
private void AddUri(XmlNode context, DekiScriptUri uri) { if (context == null) { ConvertStateToHtml(null); } // NOTE (steveb): URIs have special embedding rules; either embed it as a <img> and <a> document base on the URI file extension on the last segment XUri url = uri.Value.AsPublicUri(); MimeType mime = (url.Segments.Length > 0) ? MimeType.FromFileExtension(url.LastSegment ?? string.Empty) : MimeType.BINARY; XDoc item = mime.MainType.EqualsInvariant("image") ? DekiScriptLibrary.WebImage(url.ToString(), null, null, null) : DekiScriptLibrary.WebLink(url.ToString(), null, null, null); AddXDoc(context, item); }
public ArrayList Issues( [DekiExtParam("query expression (default: all issues)", true)] string query, [DekiExtParam("number of items to skip (default: 0)", true)] int?offset, [DekiExtParam("maximum number of items to return (default: 100)", true)] int?limit, [DekiExtParam("get only issues updated after specified date.", true)] string since ) { Login(); var request = _server.At("rest", "project", "issues"); // check if a query was provided if (!string.IsNullOrEmpty(query)) { request = request.With("filter", query); } // check if a limit and offset were provided if (offset.HasValue) { request = request.With("after", offset.Value); } request = request.With("max", limit ?? 100); // check if a date limit was provide if (!string.IsNullOrEmpty(since)) { DreamContext context = DreamContext.CurrentOrNull; CultureInfo culture = (context == null) ? CultureInfo.CurrentCulture : context.Culture; double dummy; var date = DekiScriptLibrary.CultureDateTimeParse(since, culture, out dummy); request = request.With("updatedAfter", date.ToEpoch()); } var doc = request.Get().ToDocument(); var result = new ArrayList(); foreach (var issue in doc["issue"]) { result.Add(ConvertIssue(issue)); } return(result); }
public object WebJson( [DekiExtParam("source text or source uri (default: none)", true)] string source, [DekiExtParam("caching duration in seconds (range: 300+; default: 300)", true)] double?ttl, [DekiExtParam("return nil if source could not be loaded (default: text with error message)", true)] bool?nilIfMissing, DekiScriptRuntime runtime ) { source = source ?? string.Empty; XUri uri = XUri.TryParse(source); if (uri == null) { return(DekiScriptLibrary.JsonParse(source, runtime)); } // we need to fetch an online document string response = CachedWebGet(uri, ttl, nilIfMissing); return(DekiScriptLibrary.JsonParse(response, runtime)); }
public DekiScriptOutputBuffer.Range Visit(DekiScriptReturnScope expr, DekiScriptExpressionEvaluationState state) { int marker = state.Buffer.Marker; try { if (state.FatalEvaluationError == null) { state.ThrowIfTimedout(); return(expr.Value.VisitWith(this, state)); } state.Push(state.FatalEvaluationError); } catch (DekiScriptReturnException e) { state.Push(e.Value); } catch (DekiScriptControlFlowException) { // nothing to do } catch (Exception e) { var error = DekiScriptLibrary.MakeErrorObject(e, state.Env); state.Runtime.LogExceptionInOutput(error); state.Push(new DekiScriptXml(DekiScriptLibrary.WebShowError((Hashtable)error.NativeValue))); } return(state.Buffer.Since(marker)); }
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 static DekiScriptLiteral FromNativeValue(object value) { if (value is DekiScriptLiteral) { return((DekiScriptLiteral)value); } if (value != null) { switch (AsScriptType(value.GetType())) { case DekiScriptType.BOOL: return(Constant((bool)value)); case DekiScriptType.NUM: return(Constant(SysUtil.ChangeType <double>(value))); case DekiScriptType.STR: if (value is DateTime) { return(Constant(DekiScriptLibrary.CultureDateTime((DateTime)value))); } return(Constant(value.ToString())); case DekiScriptType.MAP: return(new DekiScriptMap((Hashtable)value)); case DekiScriptType.LIST: return(new DekiScriptList((ArrayList)value)); case DekiScriptType.XML: return(Constant((XDoc)value)); case DekiScriptType.URI: return(Constant((XUri)value)); } } return(DekiScriptNil.Value); }
//--- Class Methods --- public static string AsSize(float?size) { return(DekiScriptLibrary.WebSize(size)); }
public XDoc Internal( [DekiExtParam("link")] string link, [DekiExtParam("language", true)] string language ) { // extract the link title string displayName = null; int displayNameIndex = link.IndexOf('|'); if (0 < displayNameIndex) { displayName = link.Substring(displayNameIndex + 1, link.Length - displayNameIndex - 1); link = link.Substring(0, displayNameIndex); } Title title = Title.FromUIUri(null, link, true); if (("." == title.Path) && (title.HasAnchor)) { link = "#" + AnchorEncode(title.Anchor); } else { link = LocalUrl(language, title.AsPrefixedDbPath(), title.Query); if (title.HasAnchor) { link += "#" + AnchorEncode(title.Anchor); } } // return the internal link XDoc result = new XDoc("html").Start("body").Start("a").Attr("href", link).AddNodes(DekiScriptLibrary.WebHtml(displayName ?? String.Empty, null, null, null)["body"]).End().End(); return(result); }