public static DreamMessage BuildDeletedPageContents(uint pageid) {
            ArchiveBE page = DbUtils.CurrentSession.Archive_GetPageHeadById(pageid);
            if (page == null) {
                throw new DreamAbortException(DreamMessage.NotFound(string.Format(DekiResources.RESTORE_PAGE_ID_NOT_FOUND, pageid)));
            }

            //HACKHACKHACK MaxM: Copy data to a PageBE object since parser will not work on an ArchiveBE. ArchiveBE needs to go away.
            PageBE tempP = new PageBE();
            tempP.Title = page.Title;
            tempP.SetText(page.Text);
            tempP.ContentType = page.ContentType;

            ParserResult parserResult = DekiXmlParser.Parse(tempP, ParserMode.VIEW_NO_EXECUTE);

            // TODO (steveb): this code is almost identical to the one in "GET:pages/{pageid}/contents"; consider merging

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

            // wrap the result in a content tag and return it to the user
            XDoc result = new XDoc("content").Attr("type", parserResult.ContentType);
            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
            if ((parserResult.ContentType == MimeType.TEXT.FullType) && (page.ContentType != MimeType.TEXT.FullType)) {

                // something happened during parsing
                return new DreamMessage(DreamStatus.NonAuthoritativeInformation, null, result);
            } else {
                return DreamMessage.Ok(result);
            }
        }
        /// <summary>
        /// Convert MediaWiki pages to MindTouch pages
        /// </summary>
        public void ConvertPages(out Title[] titles, out Dictionary<Title, List<PageBE>> oldTitleToPageMap) {
            Console.Out.Write("Migrating pages...  ");

            if (!MediaWikiConverterContext.Current.Merge) {
                MediaWikiDA.DeleteDWLinks();
                MediaWikiDA.DeleteDWPages();
            }

            Dictionary<Site, List<PageBE>> pagesBySite = MediaWikiDA.GetPagesBySite();
            oldTitleToPageMap = new Dictionary<Title, List<PageBE>>();

            foreach (Site site in pagesBySite.Keys) {

                // group by pages having the same title
                foreach (PageBE page in pagesBySite[site]) {

                    // convert from MediaWiki to MindTouch content
                    MWToDWContent(site, page, false);
                    Title oldTitle = MWToDWTitle(site, page.Title, false);
                    page.Title = MWToDWTitle(site, page.Title);
                    List<PageBE> pagesByTitle;
                    oldTitleToPageMap.TryGetValue(oldTitle, out pagesByTitle);
                    if (null == pagesByTitle) {
                        pagesByTitle = new List<PageBE>();
                        pagesByTitle.Add(page);
                        oldTitleToPageMap.Add(oldTitle, pagesByTitle);
                    } else {
                        pagesByTitle.Add(page);
                    }
                }

                // create a media gallery page to hold images
                PageBE mediaGalleryPage = new PageBE();
                mediaGalleryPage.Title = DWMediaGalleryTitle(site);
                mediaGalleryPage.ContentType = DekiMimeType.DEKI_TEXT;
                mediaGalleryPage.Comment = mediaGalleryPage.TIP = String.Empty;
                mediaGalleryPage.TimeStamp = mediaGalleryPage.Touched = DateTime.Now;
                mediaGalleryPage.Language = site.Language;
                mediaGalleryPage.SetText(String.Empty);
                oldTitleToPageMap.Add(mediaGalleryPage.Title, new List<PageBE>(new PageBE[] { mediaGalleryPage }));
            }

            // order by new title length so that parent pages are created before their children
            titles = new Title[oldTitleToPageMap.Keys.Count];
            int[] titleLengths = new int[titles.Length];
            oldTitleToPageMap.Keys.CopyTo(titles, 0);
            for (int i = 0; i < titles.Length; i++) {
                titleLengths[i] = GetPredominantPage(oldTitleToPageMap[titles[i]]).Title.AsUnprefixedDbPath().Length;
            }
            Array.Sort(titleLengths, titles);

            // save the pages
            foreach (Title title in titles) {
                List<PageBE> pagesByTitle = oldTitleToPageMap[title];
                PageBE predominantPage = GetPredominantPage(pagesByTitle);
                ulong oldID = predominantPage.ID;
                string oldLanguage = predominantPage.Language;

                // ensure the parent exists and set the parent id
                PageBE parentPage = EnsureParent(predominantPage.IsRedirect, predominantPage);
                if (null != parentPage) {
                    predominantPage.ParentID = parentPage.Title.IsRoot ? 0 : parentPage.ID;
                }

                // detect conflicts
                List<PageBE> conflictedPages = new List<PageBE>();
                bool differsByLanguage = true;
                foreach (PageBE page in pagesByTitle) {
                    if ((predominantPage != page) && (page.GetText(DbUtils.CurrentSession).Trim() != predominantPage.GetText(DbUtils.CurrentSession).Trim()) && !page.IsRedirect) {
                        conflictedPages.Add(page);
                        if (page.Language == predominantPage.Language) {
                            differsByLanguage = false;
                        } 
                    }
                }

                // detect if a page with the same title already exists
                PageBE pageWithMatchingName = PageBL.GetPageByTitle(predominantPage.Title);
                if ( ( null != pageWithMatchingName ) && ( 0 != pageWithMatchingName.ID ) ) {
                    conflictedPages.Add(predominantPage);
                    predominantPage = pageWithMatchingName;
                } else {

                    // for templates, add each language version in a localized section
                    if (predominantPage.Title.IsTemplate) {
                        List<string> languages = new List<string>();
                        if (!File.Exists(Path.Combine(OverrideTemplateDir, GetTemplateFilename(predominantPage.Title)))) {
                            String pageText = String.Empty;
                            foreach (PageBE page in pagesByTitle) {
                                if (page.IsRedirect) {
                                    ParserResult result = DekiXmlParser.Parse(page, ParserMode.SAVE, -1, false);
                                    languages.Add(page.Language);
                                    if(result.RedirectsToTitle != null) {
                                        pageText = String.Format("{0}<span lang='{1}' class='lang lang-{1}'>{{{{wiki.template('{2}', args)}}}}</span>", pageText, page.Language, result.RedirectsToTitle.AsPrefixedDbPath());
                                        if ("en" == page.Language || 1 == pagesByTitle.Count) {
                                            pageText = String.Format("{0}<span lang='{1}' class='lang lang-{1}'>{{{{wiki.template('{2}', args)}}}}</span>", pageText, "*", result.RedirectsToTitle.AsPrefixedDbPath());
                                        }
                                    } 
                                } else {
                                    languages.Add(page.Language);
                                    pageText = String.Format("{0}<span lang='{1}' class='lang lang-{1}'>{2}</span>", pageText, page.Language, page.GetText(DbUtils.CurrentSession));
                                    if ("en" == page.Language || 1 == pagesByTitle.Count) {
                                        pageText = String.Format("{0}<span lang='{1}' class='lang lang-{1}'>{2}</span>", pageText, "*", page.GetText(DbUtils.CurrentSession));
                                    }
                                }
                            }
                            predominantPage.SetText(pageText);
                        }
                        predominantPage.Language = String.Empty;
                        #region logging
                        if (1 < languages.Count && MediaWikiConverterContext.Current.LoggingEnabled) {
                            log["/html/body/table[@id='pagesMerged']"].Add(new XDoc("tr").Elem("td", predominantPage.Title.AsPrefixedDbPath()).Elem("td", String.Join(" ", languages.ToArray())));
                        }
                        #endregion
                    } else if (differsByLanguage && 0 < conflictedPages.Count) {
                        List<string> languages = new List<string>();
                        String pageText = String.Empty;
                        foreach (PageBE page in pagesByTitle) {
                            if (!languages.Contains(page.Language)) {
                                languages.Add(page.Language);
                                if (page.IsRedirect) {
                                    ParserResult result = DekiXmlParser.Parse(page, ParserMode.SAVE, -1, false);

                                    // TODO (steveb): not sure how to handle external redirects

                                    if(result.RedirectsToTitle != null) {
                                        page.SetText("{{wiki.page('" + result.RedirectsToTitle.AsPrefixedDbPath() + "')}}");
                                    }
                                }
                                pageText = String.Format("{0}\n<div style='border: 1px solid #777777; margin: 10px 0px; padding: 0px 10px; background-color: #eeeeee; font-weight: bold; text-align: center;'><p style='margin: 4px 0px;'>Content merged from {1}</p></div>\n{2}", pageText, page.Language, page.GetText(DbUtils.CurrentSession));
                            }
                        }
                        predominantPage.SetText(pageText);
                        predominantPage.Language = String.Empty;
                        #region logging
                        if (MediaWikiConverterContext.Current.LoggingEnabled) {
                            log["/html/body/table[@id='pagesMerged']"].Add(new XDoc("tr").Elem("td", predominantPage.Title.AsPrefixedDbPath()).Elem("td", String.Join(" ", languages.ToArray())));
                        }
                        #endregion
                    }
                    
                    // save the page
                    uint revisionNumber;
                    ulong predominantPageId = DbUtils.CurrentSession.Pages_Insert(predominantPage, 0);
                    predominantPage = PageBL.GetPageById(predominantPageId);
                    if (0 != oldID) {
                        _MWToDWPageIDMap.Add(oldLanguage + oldID, predominantPage.ID);
                    }

                    // generate redirect page if the title has changed
                    Title oldTitle = title;
                    if (predominantPage.Title != oldTitle) {
                        PageBE redirect = new PageBE();
                        redirect.Title = oldTitle;
                        redirect.SetText(String.Format(REDIRECT_TEXT, predominantPage.Title.AsPrefixedDbPath().Replace("&", "&amp;")));
                        redirect.Comment = redirect.TIP = String.Empty;
                        redirect.TimeStamp = redirect.Touched = DateTime.Now;
                        redirect.ContentType = DekiMimeType.DEKI_XML0805;
                        redirect.Language = predominantPage.Language;
                        redirect.IsRedirect = true;
                        uint tempRevisionNumber;
                        DbUtils.CurrentSession.Pages_Insert(redirect, 0);
                    }
                }

                // Report any title conflicts to the user
                if (0 < conflictedPages.Count) {
                    foreach (PageBE page in conflictedPages) {
                        #region logging
                        if (!page.IsRedirect && !differsByLanguage && MediaWikiConverterContext.Current.LoggingEnabled) {
                            log["/html/body/table[@id='removedPages']"].Add(new XDoc("tr").Elem("td", page.Title.AsPrefixedDbPath()));
                        }
                        #endregion
                    }
                }
            }

            Console.Out.WriteLine("Done!");
        }
        public void MWToDWContent(Site site, PageBE page, bool isOld) {
            try {

                // check for template content overrides
                if (OverrideTemplate(site, page)) {
                    return;
                }

                Plug converterUri = MediaWikiConverterContext.Current.MWConverterUri;
                if (null != converterUri) {
                    string interwikiInfo = String.Empty;
                    if (null != _MWInterwikiBySite) {
                        _MWInterwikiBySite.TryGetValue(site, out interwikiInfo);
                    }
                    XDoc xml = converterUri.With("title", page.Title.AsPrefixedDbPath()).With("lang", site.Language).With("site", site.Name).With("interwiki", interwikiInfo).With("text", page.GetText(DbUtils.CurrentSession)).PostAsForm().ToDocument();
                    xml.UsePrefix("mediawiki", "#mediawiki");

                    // if this is a redirect, set the page text accordingly]
                    if (page.IsRedirect) {
                        ParserResult result = DekiXmlParser.Parse(page, ParserMode.SAVE, -1, false);
                        if (result.RedirectsToTitle != null) {
                            page.SetText(String.Format(REDIRECT_TEXT, MWToDWTitle(site, Title.FromUIUri(null, xml["//mediawiki:link/@href"].Contents, true)).AsPrefixedDbPath().Replace("&", "&amp;")));
                        } else {
                            page.SetText(String.Format(REDIRECT_TEXT, xml["//mediawiki:link/@href"].Contents.Replace("&", "&amp;"), true));
                        }
                        page.ContentType = DekiMimeType.DEKI_XML0805;
                        return;
                    }

                    // remove extra paragraph tags from templates
                    if (page.Title.IsTemplate) {
                        List<XDoc> topLevelParagraphs = xml["/html/body/p"].ToList();
                        if (1 == topLevelParagraphs.Count) {
                            topLevelParagraphs[0].ReplaceWithNodes(topLevelParagraphs[0]);
                        }
                    }

                    // Map MediaWiki titles to MindTouch
                    MWToDWTitles(site, page, isOld, xml);

                    // Convert from MediaWiki output to MindTouch
                    WikiTextProcessor.Convert(site, xml, page.Title.IsTemplate);

                    // If the page is available in other languages, insert wiki.languages 
                    List<XDoc> languageList = xml["//mediawiki:meta[@type='language']"].ToList();
                    if (0 < languageList.Count) {
                        StringBuilder languageData = new StringBuilder("{{ wiki.languages( { ");
                        for (int i = 0; i < languageList.Count; i++) {
                            if (0 < i) {
                                languageData.Append(", ");
                            }
                            string relatedLanguage = languageList[i]["@language"].AsText;
                            Title relatedTitle = Title.FromUIUri(null, languageList[i].Contents, false);
                            Site relatedSite = MediaWikiConverterContext.Current.GetMWSite(relatedLanguage);
                            languageData.AppendFormat("{0}: {1}", StringUtil.QuoteString(relatedLanguage), StringUtil.QuoteString(MWToDWTitle(relatedSite, relatedTitle).AsPrefixedDbPath()));
                            languageList[i].Remove();
                        }
                        languageData.Append(" } ) }}");
                        xml["//body"].Value(languageData.ToString());
                    }

                    string contents = xml.ToString();
                    int first = contents.IndexOf("<body>");
                    int last = contents.LastIndexOf("</body>");
                    if ((first >= 0) && (last >= 0)) {
                        page.SetText(contents.Substring(first + 6, last - (first + 6)));
                        page.ContentType = DekiMimeType.DEKI_TEXT;
                    }
                }
            } catch (Exception e) {
                Console.Out.WriteLine("An unexpected exception has occurred:");
                Console.Out.WriteLine(e.GetCoroutineStackTrace());
                Console.Out.WriteLine("MediaWiki page text that produced the exception:");
                Console.Out.WriteLine(page.GetText(DbUtils.CurrentSession));
            }
        }
        public bool OverrideTemplate(Site site, PageBE page) {
            if (page.Title.IsTemplate && !String.IsNullOrEmpty(MediaWikiConverterContext.Current.MWTemplatePath)) {
                string templateFilename = GetTemplateFilename(page.Title);
                string templateOriginal = Path.Combine(OriginalTemplateDir, site.Language + "-" + templateFilename);

                // check the template against its base version to see if it's changed
                if (!File.Exists(templateOriginal)) {
                    #region logging
                    if (MediaWikiConverterContext.Current.LoggingEnabled) {
                        log["/html/body/table[@id='outdatedtemplates']"].Add(new XDoc("tr").Elem("td", MWToDWTitle(site, page.Title).AsPrefixedDbPath()));
                    }
                    #endregion
                    File.WriteAllLines(templateOriginal, new string[] { page.TimeStamp.ToString() });
                    File.AppendAllText(templateOriginal, page.GetText(DbUtils.CurrentSession));
                } else {
                    DateTime baseTimestamp = DateTime.MinValue;
                    string[] lines = File.ReadAllLines(templateOriginal);
                    if (0 < lines.Length) {
                        DateTime.TryParse(lines[0], out baseTimestamp);
                    }
                    if (DateTime.MinValue == baseTimestamp || baseTimestamp < page.TimeStamp) {
                        #region logging
                        if (MediaWikiConverterContext.Current.LoggingEnabled) {
                            log["/html/body/table[@id='outdatedtemplates']"].Add(new XDoc("tr").Elem("td", MWToDWTitle(site, page.Title).AsPrefixedDbPath()));
                        }
                        #endregion
                        File.WriteAllLines(templateOriginal, new string[] { page.TimeStamp.ToString() });
                        File.AppendAllText(templateOriginal, page.GetText(DbUtils.CurrentSession));

                    }
                }

                // check if the template's content has been overriden
                string templateOverride = Path.Combine(OverrideTemplateDir, templateFilename);
                if (File.Exists(templateOverride)) {
                    page.SetText(File.ReadAllText(templateOverride));
                    page.ContentType = DekiMimeType.DEKI_TEXT;
                    ParserResult parserResult = DekiXmlParser.Parse(page, ParserMode.SAVE, -1, false);
                    page.IsRedirect = (null != parserResult.RedirectsToTitle) || (null != parserResult.RedirectsToUri);
                    return true;
                }
            }
            return false;
        }
        private static void RestorePageRevisionsForPage(ArchiveBE[] archivedRevs, Title newTitle, uint transactionId, bool minorChange, DateTime utcTimestamp) {
            // add the most recent archive entry to the pages table
            // NOTE:  this will preserve the page id if it was saved with the archive or create a new page id if it is not available
            ArchiveBE mostRecentArchiveRev = archivedRevs[archivedRevs.Length - 1];
            PageBE restoredPage = null;
            if (0 < archivedRevs.Length) {
                restoredPage = new PageBE();
                restoredPage.Title = newTitle;
                restoredPage.Revision = mostRecentArchiveRev.Revision;
                restoredPage.MinorEdit = mostRecentArchiveRev.MinorEdit;
                bool conflict;
                PageBL.Save(restoredPage, null, mostRecentArchiveRev.Comment, mostRecentArchiveRev.Text, mostRecentArchiveRev.ContentType, mostRecentArchiveRev.Title.DisplayName, mostRecentArchiveRev.Language, -1, null, mostRecentArchiveRev.TimeStamp, mostRecentArchiveRev.LastPageId, false, false, null, false, out conflict);
                RecentChangeBL.AddRestorePageRecentChange(utcTimestamp, restoredPage, DekiContext.Current.User, String.Format(DekiResources.UNDELETED_ARTICLE, restoredPage.Title.AsPrefixedUserFriendlyPath()), minorChange, transactionId);
            }

            // add all other archive entries to the old table
            // NOTE:  this will preserve the old ids if they were saved with the archive or create new old ids if not available
            for (int i = 0; i < archivedRevs.Length - 1; i++) {
                ArchiveBE archivedRev = archivedRevs[i];
                PageBE currentPage = new PageBE();
                currentPage.Title = newTitle;
                if (i < archivedRevs.Length - 1) {
                    ParserResult parserResult = DekiXmlParser.ParseSave(currentPage, archivedRev.ContentType, currentPage.Language, archivedRev.Text, -1, null, false, null);
                    currentPage.SetText(parserResult.BodyText);
                    currentPage.ContentType = parserResult.ContentType;
                    currentPage.UserID = archivedRev.UserID;
                    currentPage.TimeStamp = archivedRev.TimeStamp;
                    currentPage.MinorEdit = archivedRev.MinorEdit;
                    currentPage.Comment = archivedRev.Comment;
                    currentPage.Language = archivedRev.Language;
                    currentPage.IsHidden = archivedRev.IsHidden;
                    currentPage.Revision = archivedRev.Revision;
                    currentPage.ID = restoredPage.ID;
                    PageBL.InsertOld(currentPage, archivedRev.OldId);
                }
            }
        }
示例#6
0
        public static OldBE Save(PageBE page, OldBE previous, string userComment, string text, string contentType, string displayName, string language, int section, string xpath, DateTime timeStamp, ulong restoredPageId, bool loggingEnabled, bool removeIllegalElements, Title relToTitle, bool overwrite, uint authorId, out bool conflict) {

            // NOTE (steveb):
            //  page: most recent page about to be overwritten
            //  previous: (optional) possible earlier page on which the current edit is based upon

            conflict = false;
            bool isNewForEventContext = page.ID == 0 || page.IsRedirect;

            // check save permissions
            IsAccessAllowed(page, 0 == page.ID ? Permissions.CREATE : Permissions.UPDATE, false);

            // validate the save
            if((0 == page.ID) && ((-1 != section) || (null != xpath))) {
                throw new ArgumentException(DekiResources.SECTION_EDIT_EXISTING_PAGES_ONLY);
            }

            // displaynames entered by user are trimmed
            if(displayName != null) {
                displayName = displayName.Trim();
            }

            if(!Title.FromDbPath(page.Title.Namespace, page.Title.AsUnprefixedDbPath(), displayName).IsValid) {
                throw new DreamAbortException(DreamMessage.Conflict(DekiResources.INVALID_TITLE));
            }

            // load old contents into current page when a section is edited
            ParserResult alternate = new ParserResult();
            ParserResult original = new ParserResult();
            if(previous != null) {

                // parse most recent version as alternate
                alternate = DekiXmlParser.Parse(page, ParserMode.RAW);

                // parse base version for three way diff
                string pageContentType = page.ContentType;
                string pageText = page.GetText(DbUtils.CurrentSession);
                page.ContentType = previous.ContentType;
                page.SetText(previous.Text);
                original = DekiXmlParser.Parse(page, ParserMode.RAW);
                page.ContentType = pageContentType;
                page.SetText(pageText);
            }

            // ensure the parent exists
            PageBE parent = EnsureParent(DekiXmlParser.REDIRECT_REGEX.IsMatch(text), page.Title);
            if(null != parent) {
                page.ParentID = parent.Title.IsRoot ? 0 : parent.ID;
            }

            // Explicitly setting the language of a talk page is not valid
            if(page.Title.IsTalk && !string.IsNullOrEmpty(language)) {
                throw new Exceptions.TalkPageLanguageCannotBeSet();
            }

            // Language is set in this order: explicitly given, already set, language of parent
            language = language ?? page.Language ?? (null != parent ? parent.Language : String.Empty);

            // talk pages always get their language from their corresponding front page
            if(page.Title.IsTalk) {
                PageBE frontPage = PageBL.GetPageByTitle(page.Title.AsFront());
                if(frontPage != null && frontPage.ID != 0) {
                    language = frontPage.Language;
                }
            }

            string nativeName = ValidatePageLanguage(language);

            // parse the content
            ParserResult parserResult = DekiXmlParser.ParseSave(page, contentType, language, text, section, xpath, removeIllegalElements, relToTitle);
            OldBE old = null;
            string comment = userComment ?? string.Empty;

            // check if this is a new page
            if(0 == page.ID) {
                AuthorizePage(DekiContext.Current.User, Permissions.CREATE, parent, false);

                if(0 == restoredPageId) {
                    if(!string.IsNullOrEmpty(comment)) {
                        comment += "; ";
                    }
                    comment += string.Format(DekiResources.PAGE_CREATED);
                    if((null == parserResult.RedirectsToTitle) && (null == parserResult.RedirectsToUri)) {
                        comment += string.Format(", " + DekiResources.PAGE_DIFF_SUMMARY_ADDED, Utils.GetPageWordCount(parserResult.MainBody));
                    }
                    page.MinorEdit = false;
                    page.IsNew = true;
                }
            }

            // if this is an existing page, ensure the content has changed and save the current page information 
            else {

                // prevent creating a redirect on a page that has non-redirect children
                if((null != parserResult.RedirectsToTitle) || (null != parserResult.RedirectsToUri)) {
                    IList<PageBE> children = DbUtils.CurrentSession.Pages_GetChildren((uint)page.ID, page.Title.Namespace, true);
                    if(0 < children.Count) {
                        throw new DreamAbortException(DreamMessage.Conflict(DekiResources.INVALID_REDIRECT));
                    }
                }

                bool displayNameChanged = page.Title.DisplayName != displayName && displayName != null;
                bool languageChanged = !StringUtil.EqualsInvariant(page.Language, language);
                if(parserResult.ContentType == page.ContentType) {
                    if(StringUtil.EqualsInvariant(parserResult.BodyText, page.GetText(DbUtils.CurrentSession))) {
                        if(!displayNameChanged && !languageChanged && !overwrite) {
                            return null;
                        }
                    } else {

                        // merge changes
                        if(previous != null) {
                            conflict = true;
                            try {
                                XDoc mergeBody = XDocDiff.Merge(original.MainBody, alternate.MainBody, parserResult.MainBody, Utils.MAX_DIFF_SIZE, ArrayMergeDiffPriority.Right, out conflict);
                                parserResult = DekiXmlParser.ParseSave(page, page.ContentType, page.Language, mergeBody.ToInnerXHtml(), -1, null, removeIllegalElements, relToTitle);
                            } catch(Exception e) {
                                _log.Error("Save", e);
                            }
                        }
                        if(!string.IsNullOrEmpty(comment)) {
                            comment += "; ";
                        }
                        if(page.IsRedirect) {
                            comment += string.Format(DekiResources.PAGE_DIFF_SUMMARY_ADDED, Utils.GetPageWordCount(parserResult.MainBody));
                        } else {
                            comment += Utils.GetPageDiffSummary(page, page.GetText(DbUtils.CurrentSession), page.ContentType, parserResult.BodyText, parserResult.ContentType);
                        }
                    }
                } else {
                    if(!string.IsNullOrEmpty(comment)) {
                        comment += "; ";
                    }
                    comment += string.Format(DekiResources.PAGE_CONTENTTYPE_CHANGED, parserResult.ContentType);
                }

                if(displayNameChanged) {
                    if(!string.IsNullOrEmpty(comment)) {
                        comment += "; ";
                    }
                    comment += string.Format(DekiResources.PAGE_DISPLAYNAME_CHANGED, displayName);

                }

                if(languageChanged) {
                    if(!string.IsNullOrEmpty(comment)) {
                        comment += "; ";
                    }
                    comment += string.Format(DekiResources.PAGE_LANGUAGE_CHANGED, nativeName);

                    // set the language on the talk page as well.
                    if(!page.Title.IsTalk) {
                        PageBE talkPage = PageBL.GetPageByTitle(page.Title.AsTalk());
                        if(talkPage != null && talkPage.ID != 0) {
                            SetPageLanguage(talkPage, language, true);
                        }
                    }
                }
                old = InsertOld(page, 0);
                page.MinorEdit = (page.UserID == DekiContext.Current.User.ID) && (DateTime.Now < page.TimeStamp.AddMinutes(15));
                page.IsNew = false;
            }

            // update the page information to reflect the new content
            page.Comment = comment;
            page.ContentType = parserResult.ContentType;
            page.Language = language;
            page.UserID = authorId;
            var bodyText = string.Empty;
            if(parserResult.RedirectsToTitle != null) {
                page.IsRedirect = true;
                bodyText = "#REDIRECT [[" + parserResult.RedirectsToTitle.AsPrefixedDbPath() + "]]";
            } else if(parserResult.RedirectsToUri != null) {
                page.IsRedirect = true;
                bodyText = "#REDIRECT [[" + parserResult.RedirectsToUri + "]]";
            } else {
                page.IsRedirect = false;
                bodyText = parserResult.BodyText;
            }
            page.SetText(bodyText);
            page.UseCache = !parserResult.HasScriptContent;
            page.TIP = parserResult.Summary;
            page.Touched = page.TimeStamp = timeStamp;

            // nametype and displayname logic
            if(string.IsNullOrEmpty(displayName) && (page.ID == 0)) {

                // new page created without a title: title comes from the name
                page.Title.DisplayName = page.Title.AsUserFriendlyDisplayName();
            } else if(!string.IsNullOrEmpty(displayName)){

                // title is provided: title set from provided value
                page.Title.DisplayName = displayName;
            } else {
                // preserve the display name of the page
            }

            // Note (arnec): Using Encoding.UTF8 because the default is Encoding.Unicode which produces a different md5sum than expected from ascii
            page.Etag = StringUtil.ComputeHashString(bodyText, Encoding.UTF8);

            // insert or update the page
            if(0 == page.ID) {
                if(restoredPageId == 0) {

                    // only set the revision if this isn't a restore.
                    page.Revision = 1;
                }
                ulong pageId = DbUtils.CurrentSession.Pages_Insert(page, restoredPageId);
                if(pageId != 0) {

                    //TODO Max: the existing page object is being modified with the ID instead of using the new object
                    page.ID = pageId;
                    if(loggingEnabled) {
                        RecentChangeBL.AddNewPageRecentChange(page.TimeStamp, page, DekiContext.Current.User, comment);
                    }

                    // Copy permissions from parent if the page is a child of homepage or Special:
                    ulong parentPageId = page.ParentID;
                    if((parentPageId == 0) && (parent != null) && (page.Title.IsMain || page.Title.IsSpecial)) {
                        parentPageId = parent.ID;
                    }
                    if(parentPageId > 0) {
                        DbUtils.CurrentSession.Grants_CopyToPage(parentPageId, page.ID);
                    }
                    
                    // never log creation of userhomepages to recentchanges
                    if(loggingEnabled && page.Title.IsUser && page.Title.GetParent().IsHomepage) {
                        loggingEnabled = false;
                    }
                }
            } else {
                page.Revision++;
                DbUtils.CurrentSession.Pages_Update(page);
                if(loggingEnabled) {
                    RecentChangeBL.AddEditPageRecentChange(page.TimeStamp, page, DekiContext.Current.User, comment, old);
                }
            }
            try {
                if(null != parserResult.Templates) {
                    ImportTemplatePages(page, parserResult.Templates.ToArray());
                }
                if(null != parserResult.Tags) {
                    ImportPageTags(page, parserResult.Tags.ToArray());
                }
                if(null != parserResult.Links) {
                    UpdateLinks(page, parserResult.Links.ToArray());
                }
            } finally {
                if(isNewForEventContext) {
                    DekiContext.Current.Instance.EventSink.PageCreate(DreamContext.Current.StartTime, page, DekiContext.Current.User);
                } else {
                    DekiContext.Current.Instance.EventSink.PageUpdate(DreamContext.Current.StartTime, page, DekiContext.Current.User);
                }
            }
            return old;
        }
示例#7
0
 public static void CopyOldToPage(OldBE old, PageBE page, Title pageTitle) {
     page.SetText(old.Text);
     page.ContentType = old.ContentType;
     page.UserID = old.UserID;
     page.TimeStamp = old.TimeStamp;
     page.MinorEdit = old.MinorEdit;
     page.Comment = old.Comment;
     page.Language = old.Language;
     page.IsHidden = old.IsHidden;
     page.Meta = old.Meta;
     page.Revision = old.Revision;
     page.ID = old.PageID;
     page.Title = pageTitle;
 }
示例#8
0
        private static void MovePageProcessRedirects(List<PageBE> pagesToMove, Dictionary<ulong, Title> newTitlesByPageId, List<PageBE> childRedirectsToRecreate) {

            //Update redirects pointing to the old locations to point to the new
            Dictionary<ulong, IList<PageBE>> redirectsByPages =
                DbUtils.CurrentSession.Pages_GetRedirects(new List<ulong>(from p in pagesToMove select p.ID));

            foreach(PageBE pageToMove in pagesToMove) {
                IList<PageBE> redirects = null;
                if(redirectsByPages.TryGetValue(pageToMove.ID, out redirects)) {
                    foreach(PageBE redirect in redirects) {
                        redirect.SetText("#REDIRECT [[" + newTitlesByPageId[pageToMove.ID].AsPrefixedDbPath() + "]]");
                        DbUtils.CurrentSession.Pages_Update(redirect);
                    }
                }
            }

            // redirects that are children of the moved root page are deleted by Pages_UpdateTitlesForMove and need to be recreated
            pagesToMove.AddRange(childRedirectsToRecreate);

            //NOTE: Pages are sorted before creating redirects to intermediate parent pages arent automatically created
            pagesToMove = pagesToMove.OrderBy(p => p.Title).ToList();
 
            foreach(PageBE movedPage in pagesToMove) {
                string text = string.Empty;
                if(movedPage.IsRedirect) {
                    //This redirect is simply recreated any may be a direct link or in the case when it's pointing to a page that was just moved,
                    //it will point to the previous title for which there's a new redirect.
                    text = movedPage.GetText(DbUtils.CurrentSession);
                } else {
                    text = "#REDIRECT [[" + newTitlesByPageId[movedPage.ID].AsPrefixedDbPath() + "]]";
                }
                PageBE oldPageRedirect = new PageBE();
                oldPageRedirect.Title = movedPage.Title;
                oldPageRedirect.SetText(text);
                PageBL.Save(oldPageRedirect, oldPageRedirect.GetText(DbUtils.CurrentSession), DekiMimeType.DEKI_TEXT, null);
                DbUtils.CurrentSession.Grants_CopyToPage(movedPage.ID, oldPageRedirect.ID);
                DekiContext.Current.Instance.EventSink.PageAliasCreate(DreamContext.Current.StartTime, oldPageRedirect, DekiContext.Current.User);
            }
        }
        private static PageBE PopulateOld(IDataRecord dr) {
            PageBE old = new PageBE();
            old.ID = DbUtils.Convert.To<ulong>(dr["rev_id"]).Value;
            old._Namespace = DbUtils.Convert.To<ushort>(dr["page_namespace"]).Value;
            old._Title = GetUTF8String(dr, "page_title");
            old.SetText(GetUTF8String(dr, "old_text"));
            old.Comment = GetUTF8String(dr, "rev_comment");
            if (MediaWikiConverterContext.Current.Merge) {
                old.UserID = MediaWikiConverterContext.Current.MergeUserId;
            } else {
                old.UserID = DbUtils.Convert.To<uint>(dr["rev_user"]).Value;
            }
            old.TimeStamp = DbUtils.ToDateTime(GetUTF8String(dr, "rev_timestamp"));
            old.MinorEdit = DbUtils.Convert.To<bool>(dr["rev_minor_edit"]).Value;
            old.ContentType = DekiMimeType.MEDIAWIKI_TEXT;
            if(MediaWikiConverterContext.Current.AttributeViaPageRevComment) {

                //Add the original revision username to the comment
                string username = GetUTF8String(dr, "rev_user_text");
                if(!string.IsNullOrEmpty(username)) {
                    old.Comment = string.Format(MediaWikiConverterContext.Current.AttributeViaPageRevCommentPattern, old.Comment, username);
                }
            }

            return old;
        }
示例#10
0
        private static PageBE PopulatePage(IDataRecord dr) {
            PageBE page = new PageBE();
            page.ID = DbUtils.Convert.To<ulong>(dr["page_id"]).Value;
            page._Namespace = DbUtils.Convert.To<ushort>(dr["page_namespace"]).Value;
            page._Title = GetUTF8String(dr, "page_title");
            string restrictions = GetUTF8String(dr, "page_restrictions");
            if ((restrictions == "sysop") || (restrictions == "move=sysop:edit=sysop")) {
                page.RestrictionID = 2;
            }
            page.Counter = DbUtils.Convert.To<uint>(dr["page_counter"]).Value;
            page.IsRedirect = DbUtils.Convert.To<bool>(dr["page_is_redirect"]).Value;
            page.IsNew = DbUtils.Convert.To<bool>(dr["page_is_new"]).Value;
            page.Touched = DbUtils.ToDateTime(GetUTF8String(dr, "page_touched"));

            if (MediaWikiConverterContext.Current.Merge) {
                page.UserID = MediaWikiConverterContext.Current.MergeUserId;
            } else {
                page.UserID = DbUtils.Convert.To<uint>(dr["rev_user"]).Value;
            }
            page.TimeStamp = DbUtils.ToDateTime(GetUTF8String(dr, "rev_timestamp"));
            page.MinorEdit = DbUtils.Convert.To<bool>(dr["rev_minor_edit"]).Value;
            page.Comment = GetUTF8String(dr, "rev_comment");
            page.SetText(GetUTF8String(dr, "old_text"));
            page.ContentType = DekiMimeType.MEDIAWIKI_TEXT;  
            page.TIP = String.Empty;

            if(MediaWikiConverterContext.Current.AttributeViaPageRevComment) {

                //Add the original revision username to the comment
                string username = GetUTF8String(dr, "rev_user_text");
                if(!string.IsNullOrEmpty(username)) {
                    page.Comment = string.Format(MediaWikiConverterContext.Current.AttributeViaPageRevCommentPattern, page.Comment, username);
                }
            }

            return page;
        }