Пример #1
0
        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);
        }
Пример #2
0
 //--- 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();
 }
Пример #3
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();
        }
Пример #4
0
 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;
 }
Пример #5
0
 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;
 }