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);
        }
Example #2
0
 internal DekiScriptXml(XDoc value, bool safe)
 {
     if (value == null)
     {
         throw new ArgumentNullException("value");
     }
     if (safe)
     {
         value = DekiScriptLibrary.CleanseHtmlDocument(value);
     }
     this.Value = value;
 }
        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));
        }
        internal DekiScriptLiteral Evaluate(DekiScriptAccess expr, DekiScriptExpressionEvaluationState state, bool evaluateProperties)
        {
            DekiScriptLiteral prefix = state.Pop(expr.Prefix.VisitWith(this, state));
            DekiScriptLiteral index  = state.Pop(expr.Index.VisitWith(this, state));

            switch (prefix.ScriptType)
            {
            case DekiScriptType.MAP: {
                DekiScriptLiteral result = ((DekiScriptMap)prefix)[index];
                if (evaluateProperties)
                {
                    result = state.Runtime.EvaluateProperty(expr.Location, result, state.Env);
                }
                return(result);
            }

            case DekiScriptType.LIST: {
                DekiScriptLiteral value  = DekiScriptExpression.Constant(index.AsNumber());
                DekiScriptLiteral result = ((DekiScriptList)prefix)[value];
                if (evaluateProperties)
                {
                    result = state.Runtime.EvaluateProperty(expr.Location, result, state.Env);
                }
                return(result);
            }

            case DekiScriptType.URI: {
                DekiScriptUri uri = (DekiScriptUri)prefix;

                // coerce the index type to STR
                index = DekiScriptExpression.Constant(index.AsString());
                if (index.ScriptType != DekiScriptType.STR)
                {
                    throw new DekiScriptBadTypeException(expr.Location, index.ScriptType, new[] { DekiScriptType.STR });
                }

                // curry the argument
                DekiScriptList args;
                if (!uri.Arguments.IsNil)
                {
                    // the uri already has curried parameters, make sure they are in LIST format; otherwise fail
                    if (uri.Arguments.ScriptType != DekiScriptType.LIST)
                    {
                        throw new DekiScriptBadTypeException(expr.Location, uri.Arguments.ScriptType, new[] { DekiScriptType.NIL, DekiScriptType.LIST });
                    }
                    args = new DekiScriptList((DekiScriptList)uri.Arguments);
                }
                else
                {
                    args = new DekiScriptList();
                }
                args.Add(index);
                return(new DekiScriptUri(uri.Value, args));
            }

            case DekiScriptType.STR: {
                DekiScriptString text = (DekiScriptString)prefix;

                // coerce the index type to NUM
                double?value = index.AsNumber();
                if (value == null)
                {
                    throw new DekiScriptBadTypeException(expr.Location, index.ScriptType, new[] { DekiScriptType.NUM });
                }

                // retrieve character at given index position
                int position = (int)value;
                if ((position < 0) || (position >= text.Value.Length))
                {
                    // index is out of bounds, return nil
                    return(DekiScriptNil.Value);
                }
                return(DekiScriptExpression.Constant(text.Value[position].ToString()));
            }

            case DekiScriptType.XML: {
                string path = index.AsString();
                if (path == null)
                {
                    throw new DekiScriptBadTypeException(expr.Location, index.ScriptType, new[] { DekiScriptType.STR });
                }
                XDoc doc = ((DekiScriptXml)prefix).Value[path];
                if (doc.HasName("html"))
                {
                    doc = DekiScriptLibrary.CleanseHtmlDocument(doc);
                }
                return(new DekiScriptXml(doc));
            }

            case DekiScriptType.NIL:
                return(DekiScriptNil.Value);
            }
            throw new DekiScriptBadTypeException(expr.Location, prefix.ScriptType, new[] { DekiScriptType.MAP, DekiScriptType.LIST, DekiScriptType.XML, DekiScriptType.STR, DekiScriptType.URI });
        }