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()); }
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); }
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)); }
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 += "§ion=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); } }
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(); }
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; }
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 += "§ion=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); } }
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; }
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; }
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; }