示例#1
0
        public void InsertNodes()
        {
            XDoc doc = new XDoc("test").Attr("attr", 1).Start("aaa").Value("1").End();

            doc.AddNodes(new XDoc("bbb").Attr("attr", 2).Value("start").Elem("ccc", "inner").Value("end"));
            Assert.AreEqual("<test attr=\"1\"><aaa>1</aaa>start<ccc>inner</ccc>end</test>", doc.ToString());
        }
示例#2
0
        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);
        }
示例#3
0
        private void BuildPropertyRow(XDoc html, ReflectedPropertyInfo member)
        {
            var xmlDoc = GetDoc(member.Signature);

            html.Start("tr")
            .Elem("td", member.MemberAccess)
            .Start("td").StartSpan("member");
            if (IsTypeInDocumentation(member.DeclaringType))
            {
                html.Link(member.UriPath, member.DisplayName);
            }
            else
            {
                html.Value(member.DisplayName);
            }
            html
            .EndSpan()
            .StartSpan("description");
            if (member.IsOverride && !member.IsInherited)
            {
                html.Value("(Override)");
            }
            html.AddNodes(xmlDoc["summary"]);
            if (member.IsInherited)
            {
                html.Value(string.Format("(Inherited from {0})", member.DeclaringType.DisplayName));
            }
            html
            .EndSpan()
            .End()      // td
            .End();     // tr
        }
        public static XDoc XmlHtml(
            [DekiScriptParam("XML document")] XDoc doc,
            [DekiScriptParam("xpath for selector", true)] string xpath
            )
        {
            if (doc.Name.EqualsInvariantIgnoreCase("html"))
            {
                return(doc);
            }
            XDoc result = new XDoc("html").Start("body");

            if (string.IsNullOrEmpty(xpath))
            {
                result.AddNodes(doc);
            }
            else
            {
                foreach (XDoc match in doc[xpath])
                {
                    result.AddNodes(match);
                }
            }
            return(CleanseHtmlDocument(result));
        }
示例#5
0
        private static void Publish(XUri uri, String login, String password, List <DreamCookie> cookies, string destination, XDoc overviewDoc, XDoc additionalInfoDoc)
        {
            string encodedPageName = XUri.DoubleEncodeSegment(destination);
            string plugPath        = "pages/=" + encodedPageName + "/contents?edittime=" + DateTime.Now.ToUniversalTime().ToString("yyyyMMddHHmmss");
            XDoc   pageContents    = null;

            // attempt to retrieve the page to determine if it already exists
            Plug         p   = Plug.New(uri).AtPath(plugPath);
            DreamMessage msg = DreamMessage.Ok();

            msg.Cookies.AddRange(cookies);
            msg = p.Get(msg, new Result <DreamMessage>()).Wait();

            switch (msg.Status)
            {
            case DreamStatus.Ok:

                // the page exists - update the auto-generated overview section
                plugPath    += "&section=1";
                pageContents = overviewDoc;
                break;

            case DreamStatus.NotFound:

                // the page does not yet exist - create it
                pageContents = overviewDoc;
                pageContents.AddNodes(additionalInfoDoc);
                break;

            default:
                throw new Exception("An error occurred during publishing:  " + msg.Status);
            }

            // save the page contents
            p   = Plug.New(uri).With("redirects", "0").AtPath(plugPath).WithCredentials(login, password);
            msg = DreamMessage.Ok(MimeType.TEXT, pageContents.ToInnerXHtml());
            msg.Cookies.AddRange(cookies);
            msg = p.Post(msg, new Result <DreamMessage>()).Wait();
            if (DreamStatus.Ok != msg.Status)
            {
                throw new Exception("An error occurred during publishing:  " + msg.Status);
            }
        }
示例#6
0
        private void AppendDiff(bool diffCacheEnabled, XDoc body, RecentChangeEntry change, RC type, Title title, IDictionary<string, XDoc> cache) {
            var resources = DekiContext.Current.Resources;
            ulong pageid = change.CurId;
            int? after = (change.Revision > 0) ? (int?)change.Revision : null;
            int? before = change.PreviousRevision;

            // append edit summary, if any
            body.Elem("p", change.Summary);

            // append comment(s)
            int count = (change.ExtraComments == null) ? (string.IsNullOrEmpty(change.Comment) ? 0 : 1) : change.ExtraComments.Count;
            switch(count) {
            case 0:

                // nothing to do
                break;
            case 1:
                body.Elem("p", (change.ExtraComments != null) ? change.ExtraComments[0].Item3 : change.Comment);
                break;
            default:
                body.Start("ol");
                foreach(var comment in ((IEnumerable<Tuplet<string, string, string>>)change.ExtraComments).Reverse()) {
                    string author = string.IsNullOrEmpty(comment.Item2) ? comment.Item1 : comment.Item2;
                    body.Elem("li", string.IsNullOrEmpty(author) ? comment.Item3 : string.Format("{0} ({1})", comment.Item3, author));
                }
                body.End();
                break;
            }

            // check if page was modified
            if(after.HasValue && before.HasValue && (after != before)) {

                // check if we have a cached version of this page diff
                XDoc diffXml = null;
                Plug store = Storage.At("site_" + XUri.EncodeSegment(DekiContext.Current.Instance.Id), DreamContext.Current.Culture.Name, "feeds", string.Format("page_{0}", pageid), string.Format("diff_{0}-{1}.xml", before, after));
                if(diffCacheEnabled) {
                    var v = store.Get(new Result<DreamMessage>(TimeSpan.MaxValue)).Wait();
                    diffXml = (v.IsSuccessful && v.HasDocument) ? v.ToDocument() : null;

                    if(diffXml != null) {

                        // TODO (steveb): this problem only exists b/c we can't determine the actual revision number that we should use for diffing (see bug 7824)

                        // check if either revision has been hidden since we computed the diff
                        var session = DbUtils.CurrentSession;
                        if(after.Value != change.CurrentRevision) {
                            OldBE afterRevision = session.Old_GetOldByRevision(pageid, (ulong)after.Value);
                            if((afterRevision == null) || afterRevision.IsHidden) {
                                diffXml = null;
                            }
                        }
                        if((diffXml != null) && (before.Value != change.CurrentRevision) && (before.Value > 0)) {
                            OldBE beforeRevision = session.Old_GetOldByRevision(pageid, (ulong)before.Value);
                            if((beforeRevision == null) || beforeRevision.IsHidden) {
                                diffXml = null;
                            }
                        }
                    }
                }
                if(diffXml == null) {
                    diffXml = new XDoc("diff");

                    // retrieve page versions
                    XDoc res = QueryPageVersions(pageid, after, before, cache);
                    XDoc beforeDoc = res["before/body"];
                    XDoc afterDoc = res["after/body"];

                    // check if either both versions or only one version were retrieved
                    XDoc diff = XDoc.Empty;
                    XDoc invisibleDiff = XDoc.Empty;
                    string summary = null;
                    if(!beforeDoc.IsEmpty && !afterDoc.IsEmpty) {
                        XDoc beforeChanges;
                        XDoc afterChanges;
                        DekiResource summaryResource = null;

                        // compute differences between 'before' and 'after' versions
                        diff = Utils.GetPageDiff(beforeDoc, afterDoc, true, DekiContext.Current.Instance.MaxDiffSize, out invisibleDiff, out summaryResource, out beforeChanges, out afterChanges);

                        // TODO (arnec): why are we using ToLower here at all and without a culture?
                        summary = resources.Localize(summaryResource).ToLower();
                    } else if(!afterDoc.IsEmpty) {

                        // since we don't have a 'before' version, just show the entire 'after' version (can happen for new pages or hidden revisions)
                        diff = afterDoc;
                    } else if(!beforeDoc.IsEmpty) {

                        // since we don't have a 'after' version, just show the entire 'before' version (can happen for hidden revisions)
                        diff = beforeDoc;
                    }

                    // add change summary
                    diffXml.Start("blockquote");
                    diffXml.Start("p").Elem("strong", summary).End();

                    // check if a diff was computed
                    if(!diff.IsEmpty) {
                        diffXml.Start("hr").Attr("width", "100%").Attr("size", "2").End();
                        diffXml.AddNodes(diff);
                        diffXml.Start("hr").Attr("width", "100%").Attr("size", "2").End();

                        // check if there are invisible changes as well to show
                        if(!invisibleDiff.IsEmpty) {
                            diffXml.Start("p").Elem("strong", resources.Localize(DekiResources.PAGE_DIFF_OTHER_CHANGES())).End();
                            diffXml.Add(invisibleDiff);
                        }
                    } else if(!invisibleDiff.IsEmpty) {

                        // only show invisible changes
                        diffXml.Start("hr").Attr("width", "100%").Attr("size", "2").End();
                        diffXml.Start("p").Elem("strong", resources.Localize(DekiResources.PAGE_DIFF_OTHER_CHANGES())).End();
                        diffXml.Add(invisibleDiff);
                    } else if(beforeDoc.IsEmpty && afterDoc.IsEmpty) {

                        // show message that page contents were not available anymore
                        diffXml.Elem("p", resources.Localize(DekiResources.PAGE_NOT_AVAILABLE()));
                    }
                    diffXml.End();

                    // store diff in cache
                    if(diffCacheEnabled && !afterDoc.IsEmpty) {
                        store.With("ttl", TimeSpan.FromDays(30).TotalSeconds).Put(diffXml, new Result<DreamMessage>(TimeSpan.MaxValue)).Block();
                    }
                }
                body.AddNodes(diffXml);
            }

            // check if we have a comment text
            if(Utils.IsPageComment(type)) {
                string text = change.CmntContent;
                if(!string.IsNullOrEmpty(text) && !change.CmntDeleted) {
                    MimeType mime = new MimeType(change.CmntMimetype ?? MimeType.TEXT_UTF8.ToString());
                    if(mime.Match(MimeType.HTML)) {
                        XDoc html = XDocFactory.From(string.Format("<html><body>{0}</body></html>", text), MimeType.HTML);
                        body.Start("blockquote").AddNodes(html["body"]).End();
                    } else {

                        // anything else should be consider to be text
                        body.Start("blockquote").Elem("p", text).End();
                    }
                } else {

                    // anything else should be consider to be text
                    body.Start("blockquote").Elem("p", resources.Localize(DekiResources.COMMENT_NOT_AVAILABLE())).End();
                }
            }

            // adds links
            body.Start("table").Attr("border", 0).Attr("padding", "5").Attr("width", "80%").Start("tr");

            // add link for viewing the page
            if(change.PageExists) {
                Title view = new Title(title);
                body.Start("td").Start("a").Attr("href", Utils.AsPublicUiUri(view, true)).Value(resources.Localize(DekiResources.VIEW_PAGE())).End().End();
            }

            // check if we need to add link for editing the page
            if(after.HasValue && before.HasValue && (after != before)) {
                Title edit = new Title(title) { Query = "action=edit" };
                body.Start("td").Start("a").Attr("href", Utils.AsPublicUiUri(edit)).Value(resources.Localize(DekiResources.EDIT_PAGE())).End().End();
            }

            // check if we need to add link for viewing the complete diff
            if(after.HasValue && before.HasValue && (after != before)) {
                Title show = new Title(title) { Query = string.Format("diff={0}&revision={1}", after.Value, before.Value) };
                body.Start("td").Start("a").Attr("href", Utils.AsPublicUiUri(show, true)).Value(resources.Localize(DekiResources.VIEW_PAGE_DIFF())).End().End();
            }

            // check if we need to add link for seeing full page history
            if(after.HasValue && before.HasValue && (after != before)) {
                Title history = new Title(title) { Query = "action=history" };
                body.Start("td").Start("a").Attr("href", Utils.AsPublicUiUri(history)).Value(resources.Localize(DekiResources.VIEW_PAGE_HISTORY())).End().End();
            }

            // check if we need to add link for banning the user
            List<KeyValuePair<string, string>> authors = change.SortedAuthors;
            if((authors == null) || (authors.Count == 0)) {
                authors = new List<KeyValuePair<string, string>> { new KeyValuePair<string, string>(change.Username, change.Fullname) };
            }
            for(int i = 0; i < authors.Count; ++i) {
                string username = authors[i].Key;
                string fullname = authors[i].Value;
                if(!string.IsNullOrEmpty(username)) {

                    // don't put up ban link for admins.
                    UserBE user = DbUtils.CurrentSession.Users_GetByName(username);
                    if(!UserBL.IsAnonymous(user) && !PermissionsBL.IsUserAllowed(user, Permissions.ADMIN)) {
                        Title ban = Title.FromUIUri(null, "Special:Userban");
                        ban.Query += string.Format("username={0}", username);
                        body.Start("td").Start("a").Attr("href", Utils.AsPublicUiUri(ban)).Value(resources.Localize(DekiResources.BAN_USER(string.IsNullOrEmpty(fullname) ? username : fullname))).End().End();
                    }
                }
            }

            // close HTML
            body.End().End();
        }
示例#7
0
        private static XDoc QueryPageVersions(ulong pageId, int? afterRevision, int? beforeRevision, IDictionary<string, XDoc> cache) {
            XDoc doc = new XDoc("diff");

            // retrieve 'after' version
            if(afterRevision.HasValue) {
                XDoc contents;
                string key = string.Format("{0}-{1}", pageId, afterRevision);

                // chek if we have a cached version
                if(!cache.TryGetValue(key, out contents)) {

                    // store response (doesn't matter if it was successful or not)
                    cache[key] = contents = GetParsedPageRevision(pageId, afterRevision.Value);
                }
                if(contents != null) {
                    doc.Start("after").Start("body");
                    doc.Elem("h1", contents["@title"].AsText);
                    doc.AddNodes(contents["body"]);
                    doc.End().End();
                }
            }

            // check if 'before' version is expected to be different
            if(beforeRevision.HasValue && (afterRevision != beforeRevision) && (beforeRevision > 0)) {
                XDoc contents;
                string key = string.Format("{0}-{1}", pageId, beforeRevision);

                // chek if we have a cached version
                if(!cache.TryGetValue(key, out contents)) {

                    // store response (doesn't matter if it was successful or not)
                    cache[key] = contents = GetParsedPageRevision(pageId, beforeRevision.Value);
                }
                if(contents != null) {
                    doc.Start("before").Start("body");
                    doc.Elem("h1", contents["@title"].AsText);
                    doc.AddNodes(contents["body"]);
                    doc.End().End();
                }
            }
            return doc;
        }
示例#8
0
        private static void Publish(XUri uri, String login, String password, List<DreamCookie> cookies, string destination, XDoc overviewDoc, XDoc additionalInfoDoc)
        {
            string encodedPageName = XUri.DoubleEncodeSegment(destination);
            string plugPath = "pages/=" + encodedPageName + "/contents?edittime=" + DateTime.Now.ToUniversalTime().ToString("yyyyMMddHHmmss");
            XDoc pageContents = null;

            // attempt to retrieve the page to determine if it already exists
            Plug p = Plug.New(uri).AtPath(plugPath);
            DreamMessage msg = DreamMessage.Ok();
            msg.Cookies.AddRange(cookies);
            msg = p.Get(msg, new Result<DreamMessage>()).Wait();

            switch(msg.Status) {
            case DreamStatus.Ok:

                // the page exists - update the auto-generated overview section
                plugPath += "&section=1";
                pageContents = overviewDoc;
                break;
            case DreamStatus.NotFound:

                // the page does not yet exist - create it
                pageContents = overviewDoc;
                pageContents.AddNodes(additionalInfoDoc);
                break;
            default:
                throw new Exception("An error occurred during publishing:  " + msg.Status);
            }

            // save the page contents
            p = Plug.New(uri).With("redirects", "0").AtPath(plugPath).WithCredentials(login, password);
            msg = DreamMessage.Ok(MimeType.TEXT, pageContents.ToInnerXHtml());
            msg.Cookies.AddRange(cookies);
            msg = p.Post(msg, new Result<DreamMessage>()).Wait();
            if(DreamStatus.Ok != msg.Status) {
                throw new Exception("An error occurred during publishing:  " + msg.Status);
            }
        }
示例#9
0
 public void InsertNodes()
 {
     XDoc doc = new XDoc("test").Attr("attr", 1).Start("aaa").Value("1").End();
     doc.AddNodes(new XDoc("bbb").Attr("attr", 2).Value("start").Elem("ccc", "inner").Value("end"));
     Assert.AreEqual("<test attr=\"1\"><aaa>1</aaa>start<ccc>inner</ccc>end</test>", doc.ToString());
 }
示例#10
0
        public Yield GetPageDiff(DreamContext context, DreamMessage request, Result<DreamMessage> response) {
            var resources = DekiContext.Current.Resources;
            string afterRev = DreamContext.Current.GetParam("revision", "head");
            string beforeRev = DreamContext.Current.GetParam("previous");
            ParserMode mode = ParserMode.EDIT;
            try {
                mode = SysUtil.ChangeType<ParserMode>(context.GetParam("mode", "edit").ToUpperInvariant());
            } catch { }

            PageBE page = PageBL_AuthorizePage(context, null, Permissions.READ, false);
            PageBL.ResolvePageRev(page, afterRev);
            ParserResult parserResult = DekiXmlParser.Parse(page, mode);

            // check if the same revision is being requested
            bool xhtml = StringUtil.EqualsInvariantIgnoreCase(context.GetParam("format", "html"), "xhtml");
            XDoc result = new XDoc("content");
            result.Attr("type", parserResult.ContentType);
            if(afterRev.EqualsInvariant(beforeRev)) {
                if(!xhtml) {
                    result.Value(parserResult.BodyText);
                } else {
                    result.AddNodes(parserResult.MainBody);
                }
            } else {
                PageBE previous = PageBL_AuthorizePage(context, null, Permissions.READ, false);
                PageBL.ResolvePageRev(previous, beforeRev);
                ParserResult previousParserResult = DekiXmlParser.Parse(previous, mode);
                DekiResource summary; // not used
                XDoc invisibleDiff;
                XDoc beforeChanges;
                XDoc afterChanges;
                XDoc combinedChanges = Utils.GetPageDiff(previousParserResult.MainBody, parserResult.MainBody, true, DekiContext.Current.Instance.MaxDiffSize, out invisibleDiff, out summary, out beforeChanges, out afterChanges);
                if(combinedChanges.IsEmpty) {

                    // if there are no visible changes and we requested the compact form, we will receive an empty document, which breaks subsequent code
                    combinedChanges = new XDoc("body");
                }
                if(!invisibleDiff.IsEmpty) {
                    combinedChanges.Start("p").Elem("strong", resources.Localize(DekiResources.PAGE_DIFF_OTHER_CHANGES())).End();
                    combinedChanges.Add(invisibleDiff);
                }
                switch(context.GetParam("diff", "combined").ToLowerInvariant()) {
                case "all":
                    if(!xhtml) {
                        result.Elem("before", beforeChanges.ToInnerXHtml());
                        result.Elem("combined", combinedChanges.ToInnerXHtml());
                        result.Elem("after", afterChanges.ToInnerXHtml());
                    } else {
                        result.Start("before").AddNodes(beforeChanges).End();
                        result.Start("combined").AddNodes(combinedChanges).End();
                        result.Start("after").AddNodes(afterChanges).End();
                    }
                    break;
                default:
                    if(!xhtml) {
                        result.Value(combinedChanges.ToInnerXHtml());
                    } else {
                        result.AddNodes(combinedChanges);
                    }
                    break;
                }
            }
            response.Return(DreamMessage.Ok(result));
            yield break;
        }
 public static XDoc XmlHtml(
     [DekiScriptParam("XML document")] XDoc doc,
     [DekiScriptParam("xpath", true)] string xpath
 ) {
     if(doc.Name.EqualsInvariantIgnoreCase("html")) {
         return doc;
     }
     XDoc result = new XDoc("html").Start("body");
     if(string.IsNullOrEmpty(xpath)) {
         result.AddNodes(doc);
     } else {
         foreach(XDoc match in doc[xpath]) {
             result.AddNodes(match);
         }
     }
     return CleanseHtmlDocument(result);
 }
        public Yield GetPageContents(DreamContext context, DreamMessage request, Result<DreamMessage> response) {
            CheckResponseCache(context, false);

            PageBE page = PageBL.GetPageFromUrl(true);
            page = PageBL.AuthorizePage(DekiContext.Current.User, Permissions.READ, page, false);

            // Retrieve the title used for path normalization (if any)
            Title relToTitle = Utils.GetRelToTitleFromUrl(context);

            PageBL.ResolvePageRev(page, DreamContext.Current.GetParam("revision", "HEAD"));

            if(page.IsHidden) {
                PermissionsBL.CheckUserAllowed(DekiContext.Current.User, Permissions.ADMIN);
            }

            int section = context.GetParam<int>("section", -1);
            if((0 == section) || (section < -1)) {
                throw new DreamAbortException(DreamMessage.BadRequest(DekiResources.SECTION_PARAM_INVALID));
            }

            // check if page should be processed as an include (used by the 'Template Dialog')
            bool isInclude = !StringUtil.EqualsInvariantIgnoreCase(context.GetParam("include", "false"), "false");
            string language = context.GetParam("lang", null);

            // extract the parser mode
            ParserMode mode = ParserMode.VIEW;
            switch(context.GetParam("mode", "view").ToLowerInvariant()) {
            case "edit":
                mode = ParserMode.EDIT;
                break;
            case "raw":
                mode = ParserMode.RAW;
                break;
            case "view":
                mode = ParserMode.VIEW;
                if(!isInclude && DekiContext.Current.Instance.StatsPageHitCounter) {
                    PageBL.IncrementViewCount(page);
                }
                break;
            case "viewnoexecute":
                mode = ParserMode.VIEW_NO_EXECUTE;
                if(!isInclude && DekiContext.Current.Instance.StatsPageHitCounter) {
                    PageBL.IncrementViewCount(page);
                }
                break;
            }

            // retrieve the page xdoc
            ParserResult parserResult;
            uint contextPageId = context.Uri.GetParam<uint>("pageid", uint.MaxValue);
            if((mode == ParserMode.VIEW) && (contextPageId != uint.MaxValue) && page.Title.IsTemplate) {

                // NOTE (steveb): page being rendered is a template and a contextual page was specified; this means we're rendering a global template page
                PageBE contextPage = PageBL.GetPageById(contextPageId);
                if(contextPage == null) {
                    response.Return(DreamMessage.BadRequest(string.Format("no page exists for pageid={0}", contextPageId)));
                    yield break;
                }
                parserResult = DekiXmlParser.ParseGlobalTemplate(contextPage, page);
            } else {
                parserResult = DekiXmlParser.Parse(page, page.ContentType, language ?? page.Language, page.GetText(DbUtils.CurrentSession), mode, isInclude, section, null, relToTitle);
            }
            if(page.Title.IsTemplate && isInclude) {
                DekiXmlParser.PostProcessTemplateInsertBody(parserResult, page);
            }

            // post process tail element
            DekiXmlParser.PostProcessParserResults(parserResult);

            // BUGBUGBUG (steveb): we cannot properly restore an old title unless it had a display title set

            // wrap the result in a content tag and return it to the user
            XDoc result = new XDoc("content")
                .Attr("type", parserResult.ContentType)
                .Attr("etag",page.Etag)
                .Attr("title", page.CustomTitle ?? page.Title.AsUserFriendlyName());

            // check if page contains unsafe content
            if(mode == ParserMode.EDIT) {
                result.Attr("unsafe", !DekiScriptLibrary.VerifyXHtml(parserResult.MainBody, true));
            }

            // check if the content should be returned as structured XML or inlined as text in an XML envelope
            if(StringUtil.EqualsInvariant(context.GetParam("format", "html"), "xhtml")) {
                result.AddNodes(parserResult.Content);
            } else {

                // encode the result as nodes of text
                foreach(XDoc entry in parserResult.Content.Elements) {
                    if(entry.HasName("body")) {
                        result.Start("body").Attr("target", entry["@target"].AsText).Value(entry.ToInnerXHtml()).End();
                    } else {
                        result.Elem(entry.Name, entry.ToInnerXHtml());
                    }
                }
            }

            // check if we hit a snag, which is indicated by a plain-text response
            DreamMessage msg;
            if((parserResult.ContentType == MimeType.TEXT.FullType) && (page.ContentType != MimeType.TEXT.FullType)) {

                // something happened during parsing
                msg = new DreamMessage(DreamStatus.NonAuthoritativeInformation, null, result);
            } else {
                msg = DreamMessage.Ok(result);
            }

            response.Return(msg);
            yield break;
        }
示例#13
0
 private void BuildPropertyRow(XDoc html, ReflectedPropertyInfo member) {
     var xmlDoc = GetDoc(member.Signature);
     html.Start("tr")
             .Elem("td", member.MemberAccess)
             .Start("td").StartSpan("member");
     if(IsTypeInDocumentation(member.DeclaringType)) {
         html.Link(member.UriPath, member.DisplayName);
     } else {
         html.Value(member.DisplayName);
     }
     html
             .EndSpan()
             .StartSpan("description");
     if(member.IsOverride && !member.IsInherited) {
         html.Value("(Override)");
     }
     html.AddNodes(xmlDoc["summary"]);
     if(member.IsInherited) {
         html.Value(string.Format("(Inherited from {0})", member.DeclaringType.DisplayName));
     }
     html
                 .EndSpan()
             .End() // td
         .End(); // tr
 }
        //--- Methods ---
        public DekiScriptEvaluationAccumulator Add(DekiScriptLiteral literal, bool safe)
        {
            if (literal == null)
            {
                throw new ArgumentNullException("literal");
            }
            if (literal is DekiScriptNil)
            {
                // nothing to do
                return(this);
            }

            // check if any value was accumulated
            if (_value == null)
            {
                if (literal is DekiScriptXml)
                {
                    _value = ((DekiScriptXml)literal).Value.Clone();
                }
                else
                {
                    _value = literal;
                }
                return(this);
            }

            // check if we can append a string value
            if (literal is DekiScriptString)
            {
                AddString(((DekiScriptString)literal).Value, safe);
                return(this);
            }
            if (!(literal is DekiScriptUri) && !(literal is DekiScriptXml))
            {
                AddString(literal.ToString(), safe);
                return(this);
            }

            // check if we need to append an XML document
            XDoc doc = literal.AsEmbeddableXml(safe);

            if (doc.IsEmpty)
            {
                return(this);
            }
            XDoc accumulator = ConvertToXml(safe);

            // build lookup for existing bodies in accumulator
            Dictionary <string, XDoc> bodies = new Dictionary <string, XDoc>();

            foreach (XmlNode node in accumulator.AsXmlNode.ChildNodes)
            {
                if (node.NodeType == XmlNodeType.Element)
                {
                    XmlElement element = (XmlElement)node;
                    if (StringUtil.EqualsInvariant(node.LocalName, "body"))
                    {
                        string target = element.GetAttribute("target");
                        bodies[target] = accumulator[node];
                    }
                }
            }

            // loop over all root children in new document
            foreach (XmlNode node in doc.AsXmlNode.ChildNodes)
            {
                if (node.NodeType == XmlNodeType.Element)
                {
                    XmlElement element = (XmlElement)node;
                    if (StringUtil.EqualsInvariant(node.LocalName, "body"))
                    {
                        string target = element.GetAttribute("target");
                        XDoc   body;
                        if (bodies.TryGetValue(target, out body))
                        {
                            // body already exists, check how it should be handled
                            string conflict = element.GetAttribute("conflict");
                            if (string.IsNullOrEmpty(conflict))
                            {
                                // default conflict resolution depends on target: no target (i.e. main body) is append, otherwise it is ignore
                                conflict = string.IsNullOrEmpty(target) ? "append" : "ignore";
                            }
                            switch (conflict)
                            {
                            case "replace":

                                // replace existing body with new one
                                body.RemoveNodes();
                                body.AddNodes(doc[node]);
                                break;

                            case "append":

                                // append nodes to existing body
                                body.AddNodes(doc[node]);
                                break;

                            case "ignore":

                                // ignore new body
                                break;
                            }
                        }
                        else
                        {
                            // target body does not exist, append it
                            accumulator.Start("body");
                            if (!string.IsNullOrEmpty(target))
                            {
                                accumulator.Attr("target", target);
                            }
                            accumulator.AddNodes(doc[node]);
                            accumulator.End();
                        }
                    }
                    else if (StringUtil.EqualsInvariant(node.LocalName, "head"))
                    {
                        XDoc head = accumulator["head"];
                        foreach (XmlNode child in node.ChildNodes)
                        {
                            head.Add(doc[child]);
                        }
                    }
                    else if (StringUtil.EqualsInvariant(node.LocalName, "tail"))
                    {
                        XDoc head = accumulator["tail"];
                        foreach (XmlNode child in node.ChildNodes)
                        {
                            head.Add(doc[child]);
                        }
                    }
                }
            }
            return(this);
        }
        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;
        }
示例#16
0
文件: PageBL.cs 项目: heran/DekiWiki
        public static XDoc RetrievePageXDoc(PageBE page, uint pageId, ParserMode mode, string language, bool isInclude, int section, Title relToTitle, bool xhtml, out ParserResult parserResult) {
            uint contextPageId = pageId;
            if((mode == ParserMode.VIEW) && (contextPageId != uint.MaxValue) && page.Title.IsTemplate) {

                // NOTE (steveb): page being rendered is a template and a contextual page was specified; this means we're rendering a global template page
                PageBE contextPage = GetPageById(contextPageId);
                if(contextPage == null) {
                    parserResult = new ParserResult();
                    return null;
                }
                parserResult = DekiXmlParser.ParseGlobalTemplate(contextPage, page);
            } else {
                parserResult = DekiXmlParser.Parse(page, page.ContentType, language ?? page.Language, page.GetText(DbUtils.CurrentSession), mode, isInclude, section, null, relToTitle);
            }
            if(page.Title.IsTemplate && isInclude) {
                DekiXmlParser.PostProcessTemplateInsertBody(parserResult, page);
            }

            // post process tail element
            DekiXmlParser.PostProcessParserResults(parserResult);

            // BUGBUGBUG (steveb): we cannot properly restore an old title unless it had a display title set

            // wrap the result in a content tag and return it to the user
            XDoc result = new XDoc("content")
                    .Attr("type", parserResult.ContentType)
                    .Attr("etag", page.Etag)
                    .Attr("title", page.CustomTitle ?? page.Title.AsUserFriendlyName());

            // check if page contains unsafe content
            if(mode == ParserMode.EDIT) {
                result.Attr("unsafe", !DekiScriptLibrary.VerifyXHtml(parserResult.MainBody, true));
            }

            if(xhtml) {
                result.AddNodes(parserResult.Content);
            } else {

                // encode the result as nodes of text
                foreach(XDoc entry in parserResult.Content.Elements) {
                    if(entry.HasName("body")) {
                        result.Start("body").Attr("target", entry["@target"].AsText).Value(entry.ToInnerXHtml()).End();
                    } else {
                        result.Elem(entry.Name, entry.ToInnerXHtml());
                    }
                }
            }
            return result;
        }