public static RecentChangeEntry FromXml(XDoc doc) { var result = new RecentChangeEntry(); result.CmntContent = doc["cmnt_content"].AsText; result.CmntDeleted = (doc["cmnt_deleted"].AsInt.GetValueOrDefault() != 0); result.CmntId = doc["cmnt_id"].AsULong; result.CmntMimetype = doc["cmnt_content_mimetype"].AsText; result.CmntNumber = doc["cmnt_number"].AsInt; result.Comment = doc["rc_comment"].AsText; result.CurId = doc["rc_cur_id"].AsULong.GetValueOrDefault(); result.Fullname = doc["rc_full_name"].AsText; result.Id = doc["rc_id"].AsULong.GetValueOrDefault(); result.LastOldId = doc["rc_last_oldid"].AsULong.Value; result.MovedToNs = (NS)doc["rc_moved_to_ns"].AsInt.Value; result.MovedToTitle = doc["rc_moved_to_title"].AsText; result.Namespace = (NS)doc["rc_namespace"].AsInt.Value; result.OldIsHidden = (doc["old_is_hidden"].AsInt.GetValueOrDefault() != 0); result.PageExists = doc["rc_page_exists"].AsInt.GetValueOrDefault() != 0; result.Revision = doc["rc_revision"].AsInt ?? 0; result.ThisOldId = doc["rc_this_oldid"].AsULong.Value; result.Timestamp = DbUtils.ToDateTime(doc["rc_timestamp"].AsText); result.Title = doc["rc_title"].AsText; result.Type = (RC)(doc["rc_type"].AsInt ?? 0); result.Username = doc["rc_user_name"].AsText ?? string.Empty; return(result); }
//--- Class Methods --- public static void AppendXml(this RecentChangeEntry change, XDoc doc) { doc.Start("change"); doc.Elem("rc_id", change.Id); if (change.ExtraComments != null) { foreach (var comment in change.ExtraComments) { doc.Start("rc_comment") .Attr("author", comment.Item1) .Attr("fullname", comment.Item2) .Value(comment.Item3) .End(); } } else { doc.Elem("rc_comment", change.Comment); } doc.Elem("rc_cur_id", change.CurId); doc.Elem("rc_last_oldid", change.LastOldId); doc.Elem("rc_this_oldid", change.ThisOldId); doc.Elem("rc_namespace", (int)change.Namespace); doc.Elem("rc_timestamp", DbUtils.ToString(change.Timestamp)); doc.Elem("rc_title", change.Title); doc.Elem("rc_type", (int)change.Type); doc.Elem("rc_moved_to_ns", (int)change.MovedToNs); doc.Elem("rc_moved_to_title", change.MovedToTitle); if ((change.SortedAuthors != null) && (change.SortedAuthors.Count > 1)) { foreach (var author in change.SortedAuthors) { doc.Elem("rc_user_name", author.Key); doc.Elem("rc_full_name", author.Value); } } else { doc.Elem("rc_user_name", change.Username); doc.Elem("rc_full_name", change.Fullname); } doc.Elem("rc_page_exists", change.PageExists ? 1 : 0); doc.Elem("rc_revision", change.Revision); doc.Elem("cmnt_id", change.CmntId); doc.Elem("cmnt_number", change.CmntNumber); doc.Elem("cmnt_content", change.CmntContent); doc.Elem("cmnt_content_mimetype", change.CmntMimetype); doc.Elem("cmnt_deleted", change.CmntDeleted ? 1 : 0); doc.Elem("old_is_hidden", change.OldIsHidden); doc.Elem("edit_count", change.EditCount); doc.Elem("rc_prev_revision", change.PreviousRevision); doc.Elem("rc_summary", change.Summary); doc.End(); }
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 bool IsUserPageCreation(RecentChangeEntry item) { if(!(item.Namespace == NS.USER && item.Type == RC.NEW) ) { return false; } var title = Title.FromDbPath(item.Namespace, item.Title, null); var parent = title.GetParent(); return parent != null && parent.IsRoot; }
public static RecentChangeEntry FromXml(XDoc doc) { var result = new RecentChangeEntry(); result.CmntContent = doc["cmnt_content"].AsText; result.CmntDeleted = (doc["cmnt_deleted"].AsInt.GetValueOrDefault() != 0); result.CmntId = doc["cmnt_id"].AsULong; result.CmntMimetype = doc["cmnt_content_mimetype"].AsText; result.CmntNumber = doc["cmnt_number"].AsInt; result.Comment = doc["rc_comment"].AsText; result.CurId = doc["rc_cur_id"].AsULong.GetValueOrDefault(); result.Fullname = doc["rc_full_name"].AsText; result.Id = doc["rc_id"].AsULong.GetValueOrDefault(); result.LastOldId = doc["rc_last_oldid"].AsULong.Value; result.MovedToNs = (NS)doc["rc_moved_to_ns"].AsInt.Value; result.MovedToTitle = doc["rc_moved_to_title"].AsText; result.Namespace = (NS)doc["rc_namespace"].AsInt.Value; result.OldIsHidden = (doc["old_is_hidden"].AsInt.GetValueOrDefault() != 0); result.PageExists = doc["rc_page_exists"].AsInt.GetValueOrDefault() != 0; result.Revision = doc["rc_revision"].AsInt ?? 0; result.ThisOldId = doc["rc_this_oldid"].AsULong.Value; result.Timestamp = DbUtils.ToDateTime(doc["rc_timestamp"].AsText); result.Title = doc["rc_title"].AsText; result.Type = (RC)(doc["rc_type"].AsInt ?? 0); result.Username = doc["rc_user_name"].AsText ?? string.Empty; return result; }