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 }
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); }
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"); } }
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); }
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); }
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; }
public void AttachmentRestore(DateTime eventTime, ResourceBE attachment, UserBE user) { PageDependentChanged(eventTime, PageBL.GetPageById(attachment.ParentPageId.Value), user, FILES, RESTORE); AttachmentChanged(eventTime, attachment, RESTORE); }
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); }
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); }
//--- 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); } } }