Пример #1
0
        private void NotifyPropertyParent(DateTime eventTime, ResourceBE prop, UserBE user, ResourceBE.ParentType parentType, string action)
        {
            if (parentType == ResourceBE.ParentType.PAGE && prop.ParentPageId != null)
            {
                PageBE parentPage = PageBL.GetPageById(prop.ParentPageId.Value);
                if (parentPage != null)
                {
                    PageDependentChanged(eventTime, parentPage, user, PROPERTY, action);
                }
            }
            else if (parentType == ResourceBE.ParentType.USER)
            {
                // Owner of property may not be same as requesting user.
                // The dependentschanged event is triggered on the property owner.
                if (prop.ParentUserId != null)
                {
                    // Optimization to avoid a db call when operating on your own user property.
                    if (user.ID != prop.ParentUserId.Value)
                    {
                        user = UserBL.GetUserById(prop.ParentUserId.Value);
                        if (user == null)
                        {
                            _log.WarnFormat("Could not find owner user (id: {0}) of user property (key: {1})", prop.ParentUserId.Value, prop.Name);
                            return;
                        }
                    }
                }

                UserDependentChanged(eventTime, user, PROPERTY, action);
            }

            //TODO (maxm): trigger file property changes
        }
Пример #2
0
        internal static Title GetRelToTitleFromUrl(DreamContext context)
        {
            Title relToTitle = null;
            uint  rootId     = context.GetParam <uint>("relto", 0);

            if (0 == rootId)
            {
                string path = context.GetParam("reltopath", null);
                if (null != path)
                {
                    relToTitle = Title.FromPrefixedDbPath(path, null);
                }
            }
            else
            {
                PageBE rootPage = PageBL.GetPageById(rootId);
                if ((null == rootPage) || (0 == rootPage.ID))
                {
                    throw new PageIdInvalidArgumentException();
                }
                else
                {
                    relToTitle = rootPage.Title;
                }
            }
            if ((null != relToTitle) && relToTitle.IsTalk)
            {
                throw new PageReltoTalkInvalidOperationException();
            }
            return(relToTitle);
        }
Пример #3
0
        private void PropertyChanged(DateTime eventTime, ResourceBE prop, UserBE user, ResourceBE.ParentType parentType, XUri parentUri, params string[] path)
        {
            try {
                string parent = string.Empty;
                switch (parentType)
                {
                case ResourceBE.ParentType.PAGE:
                    parent = PAGES;
                    break;

                case ResourceBE.ParentType.FILE:
                    parent = FILES;
                    break;

                case ResourceBE.ParentType.USER:
                    parent = USERS;
                    break;

                case ResourceBE.ParentType.SITE:
                    parent = SITE;
                    break;
                }
                XUri     channel  = _channel.At(parent).At(PROPERTY).At(path);
                XUri     resource = prop.PropertyInfoUri(parentUri);
                string[] origin   = new string[] { resource.ToString() };
                XDoc     doc      = new XDoc("deki-event")
                                    .Elem("channel", channel)
                                    .Elem("name", prop.Name)
                                    .Elem("uri", resource)
                                    .Start("content")
                                    .Attr("mime-type", prop.MimeType.FullType)
                                    .Attr("size", prop.Size)
                                    .Attr("href", prop.PropertyContentUri(parentUri));
                if (prop.MimeType.MainType == MimeType.TEXT.MainType && prop.Size < 256)
                {
                    doc.Value(ResourceContentBL.Instance.Get(prop).ToText());
                }
                doc.End();
                if (parentType == ResourceBE.ParentType.PAGE)
                {
                    doc.Elem("pageid", prop.ParentPageId ?? 0);
                }
                else if (parentType == ResourceBE.ParentType.USER)
                {
                    doc.Elem("userid", prop.ParentUserId ?? 0);
                }
                else if (parentType == ResourceBE.ParentType.FILE)
                {
                    ResourceBE attachment = ResourceBL.Instance.GetResource(prop.ParentId.Value);
                    doc.Elem("fileid", attachment.MetaXml.FileId ?? 0);
                    PageDependentChanged(eventTime, PageBL.GetPageById(attachment.ParentPageId.Value), user, ArrayUtil.Concat(new string[] { FILES, PROPERTY }, path));
                }
                Queue(eventTime, channel, resource, origin, doc);
            } catch (Exception e) {
                _log.WarnExceptionMethodCall(e, "PropertyChanged", "event couldn't be created");
            }
        }
Пример #4
0
 private IList <TagBE> AssignDefinePages(IList <TagBE> tags)
 {
     foreach (TagBE tag in tags)
     {
         if (tag.Type == TagType.DEFINE)
         {
             ulong pageId = _session.Tags_GetPageIds(tag.Id).FirstOrDefault();
             if (0 != pageId)
             {
                 tag.DefinedTo = PageBL.GetPageById(pageId);
             }
         }
     }
     return(tags);
 }
Пример #5
0
        private ResourceBE GetAttachmentFromUrl(DreamContext context, bool mustExist, out PageBE page, bool allowRevs, bool allowDeleted)
        {
            ResourceBE file     = null;
            int        revision = ResourceBE.HEADREVISION;

            page = null;
            string revStr = DreamContext.Current.GetParam("revision", "head").Trim();

            if (allowRevs)
            {
                if (!StringUtil.EqualsInvariantIgnoreCase(revStr, "head") && !StringUtil.EqualsInvariantIgnoreCase(revStr, "0"))
                {
                    if (!int.TryParse(revStr, out revision))
                    {
                        throw new RevisionHeadOrIntInvalidArgumentException();
                    }
                }
            }
            else if (!StringUtil.EqualsInvariantIgnoreCase(revStr, "head") && !StringUtil.EqualsInvariantIgnoreCase(revStr, "0"))
            {
                throw new AttachmentUnsupportedRevisionInvalidArgumentException();
            }

            uint fileId = DreamContext.Current.GetParam <uint>("fileid", 0);

            if (fileId != 0)
            {
                uint resourceId = ResourceMapBL.GetResourceIdByFileId(fileId) ?? 0;
                if (resourceId > 0)
                {
                    // use resourceid to retrieve attachment
                    file = ResourceBL.Instance.GetResourceRevision(resourceId, revision);
                }
                if (file != null)
                {
                    page = PageBL.GetPageById(file.ParentPageId.Value);
                }
            }
            else
            {
                // use filename to retrieve attachment
                string fileName = GetFilenameFromPathSegment(DreamContext.Current.GetParam <string>("filename"));
                page = PageBL_GetPageFromUrl(context, true);
                DeletionFilter deleteFilter = allowDeleted ? DeletionFilter.ANY : DeletionFilter.ACTIVEONLY;
                file = AttachmentBL.Instance.GetPageAttachment(page.ID, fileName, deleteFilter);
                if (revision != ResourceBE.HEADREVISION)
                {
                    file = ResourceBL.Instance.GetResourceRevision(file.ResourceId, revision);
                }
            }
            if (file == null)
            {
                if (mustExist)
                {
                    throw new AttachmentNotFoundException();
                }
            }
            else
            {
                if (!allowDeleted)
                {
                    if (file.ResourceIsDeleted || page == null)
                    {
                        // TODO (maxm): Throw a 404 status if file is not marked as deleted but the parent page cannot be found.
                        // This may be caused by an unfinished page delete operation that didn't mark the file as deleted.
                        throw new AttachmentRemovedNotFoundException();
                    }
                }
            }

            return(file);
        }
Пример #6
0
        public Yield GetNavigationFull(DreamContext context, DreamMessage request, Result <DreamMessage> response)
        {
            CheckResponseCache(context, false);

            PageBE page = PageBL_GetPageFromUrl(context, false);

            if (page.Title.IsTalk)
            {
                page = PageBL.GetPageByTitle(page.Title.AsFront());
            }

            // check if requestest page exists, otherwise find nearest parent
            uint         new_page_id = NavBL.NEW_PAGE_ID;
            ulong        homepageId  = DekiContext.Current.Instance.HomePageId;
            List <NavBE> list;
            bool         expandableNav = context.GetParam("type", "compact").EqualsInvariantIgnoreCase("expandable");

            // check if a page was found
            if (page.ID == 0)
            {
                // find nearest ancestor and authorize access
                PageBE ancestor = page;
                while (!ancestor.Title.IsHomepage)
                {
                    // fetch ancestor page based on title
                    ulong id = DbUtils.CurrentSession.Nav_GetNearestParent(ancestor.Title);
                    ancestor = PageBL.GetPageById(id);
                    if (PermissionsBL.IsUserAllowed(DekiContext.Current.User, ancestor, Permissions.BROWSE))
                    {
                        break;
                    }

                    // determine parent page title
                    Title title = ancestor.Title.GetParent();
                    if (title == null)
                    {
                        // current ancestor was the homepage
                        break;
                    }
                    ancestor = new PageBE {
                        Title = title
                    };
                }
                if (ancestor.ID == 0)
                {
                    ancestor = PageBL.GetHomePage();
                }
                list = NavBL.QueryNavTreeData(ancestor, context.Culture, expandableNav).ToList();

                // find the nearest parent node and increase its child count
                foreach (NavBE nearestAncestors in list)
                {
                    if (nearestAncestors.Id == ancestor.ID)
                    {
                        nearestAncestors.ChildCount = nearestAncestors.ChildCount + 1;
                        break;
                    }
                }

                // for each missing node, generate a dummy page and insert it into result set
                ulong        ancestor_id       = ancestor.ID;
                string[]     ancestor_segments = ancestor.Title.AsUnprefixedDbSegments();
                string[]     new_page_segments = page.Title.AsUnprefixedDbSegments();
                List <NavBE> newNodes          = new List <NavBE>(32);
                for (int i = ancestor_segments.Length; i < new_page_segments.Length; ++i)
                {
                    string title = string.Join("/", new_page_segments, 0, i + 1);

                    // create dummy node with <page><page_id /><page_namespace /><page_title ><page_parent /><page_children /></page>
                    NavBE newPage = new NavBE {
                        Id         = new_page_id,
                        NameSpace  = (ushort)page.Title.Namespace,
                        Title      = title,
                        ParentId   = (ancestor_id == homepageId) ? 0 : ancestor_id,
                        ChildCount = (i == new_page_segments.Length - 1) ? 0 : 1
                    };
                    newNodes.Add(newPage);

                    // update page information
                    page.ID       = new_page_id;
                    page.ParentID = ancestor_id;
                    ancestor_id   = new_page_id++;
                }

                // check if we need to remove the children nodes of the ancestor
                ancestor_id = (ancestor.ID == homepageId) ? 0 : (uint)ancestor.ID;
                if (!expandableNav && (new_page_segments.Length - ancestor_segments.Length) > 1)
                {
                    // remove ancestor children and add new dummy nodes
                    for (int start = 0; start < list.Count; ++start)
                    {
                        // check if we found a matching child
                        if ((list[start].ParentId == ancestor_id) && (list[start].Id != homepageId))
                        {
                            // look for last child to remove so we can remove an entire range at once
                            int end = start + 1;
                            for (; (end < list.Count) && (list[end].ParentId == ancestor_id) && (list[end].Id != homepageId); ++end)
                            {
                            }
                            list.RemoveRange(start, end - start);
                            --start;
                        }
                    }
                }
                else
                {
                    // find where among the ancestor children we need to insert the dummy node
                    for (int index = 0; index < list.Count; ++index)
                    {
                        NavBE current = list[index];
                        if ((current.ParentId == ancestor_id) && (current.Id != homepageId))
                        {
                            string[] parts = Title.FromDbPath(NS.UNKNOWN, current.Title, current.DisplayName).AsUnprefixedDbSegments();
                            if ((parts.Length > 0) && (new_page_segments.Length > 0) && (string.Compare(parts[parts.Length - 1], new_page_segments[parts.Length - 1], true, context.Culture) > 0))
                            {
                                // found the spot
                                list.InsertRange(index, newNodes);
                                newNodes = null;
                                break;
                            }
                        }
                    }
                }

                // check if we didn't find the spot
                if (newNodes != null)
                {
                    // add new nodes to the end
                    list.AddRange(newNodes);
                }
            }
            else
            {
                list = NavBL.QueryNavTreeData(page, context.Culture, expandableNav).ToList();
            }

            // find first parent
            ulong parent_id    = homepageId;
            int   parent_index = -1;

            for (int i = 0; i < list.Count; ++i)
            {
                if (list[i].Id == parent_id)
                {
                    parent_index = i;
                    break;
                }
            }
            if (parent_index == -1)
            {
                throw new Exception("unexpected [homepage not found]");
            }

            // add any missing ancestor nodes (might have been removed by permission check or might simply not exist)
            string[] page_segments = page.Title.AsUnprefixedDbSegments();
            ushort   ns            = (ushort)page.Title.Namespace;

            for (int i = 0; i <= page_segments.Length; ++i)
            {
                string title = string.Join("/", page_segments, 0, i);

                // loop over all nodes
                bool found = false;
                for (int j = 0; j < list.Count; ++j)
                {
                    NavBE node = list[j];

                    // NOTE (steveb): we walk the path one parent at a time; however, there are a few special cases, because of namespaces
                    //      for instance, the parent page of User:Bob is the homepage (ditto for Template:Page), but the parent page of Admin:Config is Admin:

                    // check if we found a node matching the current title
                    if ((string.Compare(node.Title, title, true, context.Culture) == 0) && (((i == 0) && (ns != (ushort)NS.ADMIN)) ? (node.NameSpace == (ushort)NS.MAIN) : (node.NameSpace == ns)))
                    {
                        found = true;

                        // let's make sure node is pointing to right parent
                        node.ParentId = (parent_id == homepageId) ? 0 : parent_id;
                        parent_id     = node.Id;
                        parent_index  = j;
                        break;
                    }
                }
                if (!found)
                {
                    // node is missing, let's create a new one
                    NavBE newPage = new NavBE {
                        Id        = new_page_id,
                        NameSpace = (ushort)page.Title.Namespace,
                        Title     = title,
                        ParentId  = (parent_id == homepageId) ? 0 : parent_id, ChildCount = 1
                    };

                    // add new page after parent
                    list.Insert(parent_index + 1, newPage);
                    parent_id    = new_page_id++;
                    parent_index = parent_index + 1;
                }
            }

            // build response
            if (ShowDebug(context))
            {
                response.Return(DreamMessage.Ok(NavBL.ConvertNavPageListToDoc(list)));
            }
            else
            {
                XDoc result = expandableNav ? NavBL.ComputeExpandableNavigationDocument(list, page, 0, 0, false) : NavBL.ComputeNavigationDocument(list, page, 0, 0, false, context.GetParam("width", int.MaxValue));
                if (ShowXml(context))
                {
                    response.Return(DreamMessage.Ok(result));
                }
                else
                {
                    response.Return(DreamMessage.Ok(new XDoc("tree").Value(result.Contents)));
                }
            }
            yield break;
        }
Пример #7
0
 public void AttachmentRestore(DateTime eventTime, ResourceBE attachment, UserBE user)
 {
     PageDependentChanged(eventTime, PageBL.GetPageById(attachment.ParentPageId.Value), user, FILES, RESTORE);
     AttachmentChanged(eventTime, attachment, RESTORE);
 }
Пример #8
0
 public void AttachmentMove(DateTime eventTime, ResourceBE attachment, PageBE sourcePage, UserBE user)
 {
     PageDependentChanged(eventTime, sourcePage, user, FILES, DELETE);
     PageDependentChanged(eventTime, PageBL.GetPageById(attachment.ParentPageId.Value), user, FILES, CREATE);
     AttachmentChanged(eventTime, attachment, MOVE);
 }
Пример #9
0
        private static XDoc AppendCommentXml(XDoc doc, CommentBE comment, string suffix, bool?includeParentInfo)
        {
            bool   requiresEnd    = false;
            string commentElement = string.IsNullOrEmpty(suffix) ? "comment" : "comment." + suffix;

            if (doc == null || doc.IsEmpty)
            {
                doc = new XDoc(commentElement);
            }
            else
            {
                doc.Start(commentElement);
                requiresEnd = true;
            }

            doc.Attr("id", comment.Id).Attr("href", CommentBL.GetUri(comment));

            //include parentinfo by default if the parent page is populated
            PageBE page = PageBL.GetPageById(comment.PageId);

            if (page != null && (includeParentInfo ?? true))
            {
                doc.Add(PageBL.GetPageXml(page, "parent"));
            }

            UserBE posterUser = UserBL.GetUserById(comment.PosterUserId);

            if (posterUser != null)
            {
                doc.Add(UserBL.GetUserXml(posterUser, "createdby", Utils.ShowPrivateUserInfo(posterUser)));
            }
            doc.Start("date.posted").Value(comment.CreateDate).End();
            doc.Start("title").Value(comment.Title).End();
            doc.Start("number").Value(comment.Number).End();

            //Note (MaxM): Replytoid/replies not yet exposed
            //if (ReplyToId.HasValue) {
            //    doc.Start("comment.replyto")
            //        .Attr("number", ReplyToId.Value.ToString())
            //        .Attr("href", DekiContext.Current.ApiUri.At("pages", PageId.ToString(), "comments", ReplyToId.Value.ToString())).End();
            //}

            bool displayContent = true;

            //Only display content for nondeleted comments or for admins
            if (comment.IsCommentMarkedAsDeleted)
            {
                displayContent = PermissionsBL.IsUserAllowed(DekiContext.Current.User, Permissions.ADMIN);
            }

            if (displayContent)
            {
                doc.Start("content")
                .Attr("type", comment.ContentMimeType)
                .Attr("href", CommentBL.GetUri(comment).At("content"))
                .Value(comment.Content).End();
            }

            if (comment.LastEditUserId.HasValue)
            {
                UserBE lastEditUser = UserBL.GetUserById(comment.LastEditUserId.Value);
                if (null != lastEditUser)
                {
                    doc.Add(UserBL.GetUserXml(lastEditUser, "editedby", Utils.ShowPrivateUserInfo(lastEditUser)));
                    doc.Start("date.edited").Value(comment.LastEditDate).End();
                }
            }

            if (comment.IsCommentMarkedAsDeleted && comment.DeleterUserId.HasValue)
            {
                UserBE deleteUser = UserBL.GetUserById(comment.DeleterUserId.Value);
                if (null != deleteUser)
                {
                    doc.Add(UserBL.GetUserXml(deleteUser, "deletedby", Utils.ShowPrivateUserInfo(deleteUser)));
                    doc.Start("date.deleted").Value(comment.DeleteDate).End();
                }
            }

            if (requiresEnd)
            {
                doc.End(); //comment
            }

            return(doc);
        }
Пример #10
0
        //--- Methods ---
        public void Append(XDoc exportDoc)
        {
            _manifestDoc.Attr("date.created", DateTime.UtcNow).Attr("preserve-local", false);
            foreach (XDoc exportXml in exportDoc.Elements)
            {
                // Retrieve the current page
                try {
                    if (exportXml.HasName("page"))
                    {
                        // Generate the manifest and request needed to export the page
                        PageBE page = null;
                        if (!exportXml["@id"].IsEmpty)
                        {
                            uint pageId = DbUtils.Convert.To <uint>(exportXml["@id"].Contents, 0);
                            if (0 < pageId)
                            {
                                page = PageBL.GetPageById(pageId);
                            }
                        }
                        else if (!exportXml["@path"].IsEmpty)
                        {
                            page = PageBL.GetPageByTitle(Title.FromPrefixedDbPath(exportXml["@path"].Contents, null));
                        }
                        if ((null == page) || (0 == page.ID))
                        {
                            throw new PageNotFoundException();
                        }

                        // Check whether to exclude subpages, files, and/or properties
                        bool recursive            = exportXml["@recursive"].AsBool ?? false;
                        ExportExcludeType exclude = ExportExcludeType.NONE;
                        if (!exportXml["@exclude"].IsEmpty)
                        {
                            exclude = SysUtil.ChangeType <ExportExcludeType>(exportXml["@exclude"].Contents);
                        }

                        // Export the page
                        PageExport(recursive, exclude, page);
                    }
                    else if (exportXml.HasName("file"))
                    {
                        // Generate the manifest and request needed to export the file
                        ResourceBE file = null;
                        if (!exportXml["@id"].IsEmpty)
                        {
                            uint fileId = DbUtils.Convert.To <uint>(exportXml["@id"].Contents, 0);
                            if (0 < fileId)
                            {
                                uint resourceId = ResourceMapBL.GetResourceIdByFileId(fileId) ?? 0;
                                if (resourceId > 0)
                                {
                                    file = ResourceBL.Instance.GetResource(resourceId);
                                }
                            }
                        }
                        if (null == file)
                        {
                            throw new AttachmentNotFoundException();
                        }

                        // Check whether to exclude properties
                        ExportExcludeType exclude = ExportExcludeType.NONE;
                        if (!exportXml["@exclude"].IsEmpty)
                        {
                            exclude = SysUtil.ChangeType <ExportExcludeType>(exportXml["@exclude"].Contents);
                        }

                        // Perform the file export
                        PageBE page = PageBL.GetPageById(file.ParentPageId.Value);
                        page = PageBL.AuthorizePage(DekiContext.Current.User, Permissions.READ, page, false);
                        AttachmentExport(exclude, page, file);
                    }
                    else
                    {
                        throw new DreamResponseException(DreamMessage.NotImplemented(exportXml.Name));
                    }
                } catch (ResourcedMindTouchException e) {
                    AddError(e.Message, (int)e.Status, exportXml);
                } catch (DreamAbortException e) {
                    AddError(e.Message, (int)e.Response.Status, exportXml);
                } catch (Exception e) {
                    AddError(e.Message, (int)DreamStatus.InternalError, exportXml);
                }
            }
        }