コード例 #1
0
ファイル: EntityFactories.cs プロジェクト: priaonehaha/HnD
        /// <summary>Creates a new, empty SupportQueueThreadEntity object.</summary>
        /// <returns>A new, empty SupportQueueThreadEntity object.</returns>
        public override IEntity Create()
        {
            IEntity toReturn = new SupportQueueThreadEntity();

            // __LLBLGENPRO_USER_CODE_REGION_START CreateNewSupportQueueThread
            // __LLBLGENPRO_USER_CODE_REGION_END
            return(toReturn);
        }
コード例 #2
0
        /// <summary>
        /// Adds the thread with the ID specified to the support queue with the ID specified
        /// </summary>
        /// <param name="threadId">The thread ID.</param>
        /// <param name="queueId">The queue ID.</param>
        /// <param name="userId">The user ID of the user causing this thread to be placed in the queue specified.</param>
        /// <param name="adapter">The live adapter with an active transaction. Can be null, in which case a local transaction is used.</param>
        /// <remarks>first removes the thread from a queue if it's in a queue</remarks>
        public static async Task AddThreadToQueueAsync(int threadId, int queueId, int userId, IDataAccessAdapter adapter)
        {
            var localAdapter = adapter == null;
            var adapterToUse = adapter ?? new DataAccessAdapter();

            try
            {
                if (localAdapter)
                {
                    await adapterToUse.StartTransactionAsync(IsolationLevel.ReadCommitted, "AddThreadToQueue").ConfigureAwait(false);
                }

                // first remove the thread from any queue it's in.
                await RemoveThreadFromQueueAsync(threadId, adapterToUse);

                // then add it to the queue specified.
                var supportQueueThread = new SupportQueueThreadEntity
                {
                    ThreadID = threadId,
                    QueueID  = queueId,
                    PlacedInQueueByUserID = userId,
                    PlacedInQueueOn       = DateTime.Now
                };
                await adapterToUse.SaveEntityAsync(supportQueueThread).ConfigureAwait(false);

                if (localAdapter)
                {
                    adapterToUse.Commit();
                }
            }
            catch
            {
                if (localAdapter)
                {
                    adapterToUse.Rollback();
                }

                throw;
            }
            finally
            {
                if (localAdapter)
                {
                    adapterToUse.Dispose();
                }
            }
        }
コード例 #3
0
        /// <summary>
        /// Releases the claim on the thread specified. As the thread can be in one queue at a time, it simply has to update the SupportQueueThread entity.
        /// </summary>
        /// <param name="threadID">The thread ID.</param>
        public static void ReleaseClaimOnThread(int threadID)
        {
            SupportQueueThreadEntity supportQueueThread = new SupportQueueThreadEntity();

            supportQueueThread.FetchUsingUCThreadID(threadID);
            if (supportQueueThread.IsNew)
            {
                // not found, return
                return;
            }

            // simply reset an existing claim
            supportQueueThread.ClaimedByUserID = null;                          // nullable type, so set to null.
            supportQueueThread.ClaimedOn       = null;                          // nullable type, so set to null.

            // done, save it
            supportQueueThread.Save();
        }
コード例 #4
0
        /// <summary>
        /// Claims the thread specified for the user specified. As the thread can be in one queue at a time, it simply has to update the SupportQueueThread entity.
        /// </summary>
        /// <param name="userID">The user ID.</param>
        /// <param name="threadID">The thread ID.</param>
        public static void ClaimThread(int userID, int threadID)
        {
            SupportQueueThreadEntity supportQueueThread = new SupportQueueThreadEntity();

            supportQueueThread.FetchUsingUCThreadID(threadID);
            if (supportQueueThread.IsNew)
            {
                // not found, return
                return;
            }

            // simply overwrite an existing claim if any.
            supportQueueThread.ClaimedByUserID = userID;
            supportQueueThread.ClaimedOn       = DateTime.Now;

            // done, save it
            supportQueueThread.Save();
        }
コード例 #5
0
        /// <summary>
        /// Adds the thread with the ID specified to the support queue with the ID specified
        /// </summary>
        /// <param name="threadID">The thread ID.</param>
        /// <param name="queueID">The queue ID.</param>
        /// <param name="userID">The user ID of the user causing this thread to be placed in the queue specified.</param>
        /// <param name="transactionToUse">The transaction to use. Is not null if there's a transaction in progress.</param>
        /// <remarks>first removes the thread from a queue if it's in a queue</remarks>
        public static void AddThreadToQueue(int threadID, int queueID, int userID, Transaction transactionToUse)
        {
            // first remove the thread from any queue it's in.
            RemoveThreadFromQueue(threadID, transactionToUse);

            // then add it to the queue specified.
            SupportQueueThreadEntity supportQueueThread = new SupportQueueThreadEntity();

            supportQueueThread.ThreadID = threadID;
            supportQueueThread.QueueID  = queueID;
            supportQueueThread.PlacedInQueueByUserID = userID;
            supportQueueThread.PlacedInQueueOn       = DateTime.Now;

            if (transactionToUse != null)
            {
                // transaction in progress, add the entity to the transaction
                transactionToUse.Add(supportQueueThread);
            }
            supportQueueThread.Save();
        }
コード例 #6
0
        /// <summary>
        /// Gets the support queue thread info entity and if specified, prefetches the user entity which claimed the related thread.
        /// </summary>
        /// <param name="threadID">The thread ID.</param>
        /// <param name="prefetchClaimUser">if set to true it will </param>
        /// <returns>fetched entity if found, otherwise null</returns>
        public static SupportQueueThreadEntity GetSupportQueueThreadInfo(int threadID, bool prefetchClaimUser)
        {
            SupportQueueThreadEntity toReturn = new SupportQueueThreadEntity();
            PrefetchPath             path     = null;

            if (prefetchClaimUser)
            {
                // prefetch the user who claimed this thread (if any)
                path = new PrefetchPath((int)EntityType.SupportQueueThreadEntity);
                path.Add(SupportQueueThreadEntity.PrefetchPathClaimedByUser);
            }

            // now fetch the entity using the unique constraint on Thread by specifying the threadID passed in. Also specify the prefetch path (if any)
            toReturn.FetchUsingUCThreadID(threadID, path);
            if (toReturn.IsNew)
            {
                // not found
                return(null);
            }
            return(toReturn);
        }
コード例 #7
0
ファイル: ForumManager.cs プロジェクト: priaonehaha/HnD
        /// <summary>
        /// Creates a new thread in the given forum and places the passed in message as the first message in the thread.
        /// Caller should validate input parameters.
        /// </summary>
        /// <param name="forumID">Forum wherein the new thread will be placed</param>
        /// <param name="userID">User who started this thread</param>
        /// <param name="subject">Subject of the thread</param>
        /// <param name="messageText">First message of the thread</param>
        /// <param name="messageAsHTML">Message text as HTML</param>
        /// <param name="isSticky">Flag if the thread is sticky / pinned (true) or not (false)</param>
        /// <param name="userIDIPAddress">IP address of user calling this method</param>
        /// <param name="defaultSupportQueueID">The ID of the default support queue for this forum. If not null, the thread created will be
        /// added to the support queue with the ID specified.</param>
        /// <param name="messageID">The message ID of the new message, which is the start message in the thread.</param>
        /// <returns>ThreadID if succeeded, 0 if not.</returns>
        public static int CreateNewThreadInForum(int forumID, int userID, string subject, string messageText, string messageAsHTML, bool isSticky,
                                                 string userIDIPAddress, int?defaultSupportQueueID, bool subscribeToThread, out int messageID)
        {
            Transaction trans = new Transaction(IsolationLevel.ReadCommitted, "NewThread");

            try
            {
                DateTime postDate = DateTime.Now;

                ThreadEntity newThread = new ThreadEntity();
                newThread.ForumID               = forumID;
                newThread.IsClosed              = false;
                newThread.IsSticky              = isSticky;
                newThread.StartedByUserID       = userID;
                newThread.Subject               = subject;
                newThread.ThreadLastPostingDate = postDate;

                if (defaultSupportQueueID.HasValue)
                {
                    // a support queue has been specified as the default support queue for this forum. Add the new thread to this support queue.
                    SupportQueueThreadEntity supportQueueThread = new SupportQueueThreadEntity();
                    supportQueueThread.QueueID = defaultSupportQueueID.Value;
                    supportQueueThread.PlacedInQueueByUserID = userID;
                    supportQueueThread.PlacedInQueueOn       = DateTime.Now;
                    // assign the Thread property to the newly created thread entity, so this supportqueuethreadentity will be part of the graph
                    // of objects which will be saved.
                    supportQueueThread.Thread = newThread;
                }

                DateTime      postingDate = DateTime.Now;
                MessageEntity newMessage  = new MessageEntity();
                newMessage.MessageText       = messageText;
                newMessage.MessageTextAsHTML = messageAsHTML;
                newMessage.PostedByUserID    = userID;
                newMessage.PostingDate       = postingDate;
                newMessage.PostedFromIP      = userIDIPAddress;
                newMessage.Thread            = newThread;

                // add the newMessage entity to the transaction object. All entities saved recursively will be added automatically
                trans.Add(newMessage);

                // save the complete graph
                newMessage.Save(true);

                messageID = newMessage.MessageID;
                int threadID = newMessage.ThreadID;

                // update thread statistics, this is the task for the message manager, and we pass the transaction object so the actions will run in
                // the same transaction.
                MessageManager.UpdateStatisticsAfterMessageInsert(threadID, userID, trans, postingDate, false, subscribeToThread);

                trans.Commit();
                return(newThread.ThreadID);
            }
            catch (Exception)
            {
                trans.Rollback();
                throw;
            }
            finally
            {
                trans.Dispose();
            }
        }
コード例 #8
0
        /// <summary>
        /// Deletes the user with the ID passed in. Will reset all posts made by the user to the userid 0.
        /// </summary>
        /// <param name="userId">The user ID.</param>
        /// <remarks>Can't delete user 0</remarks>
        /// <returns>true if succeeded, false otherwise</returns>
        public static async Task <bool> DeleteUserAsync(int userId)
        {
            if (userId <= 1)
            {
                // can't delete the Anonymous user nor the admin user
                return(false);
            }

            var toDelete = await UserGuiHelper.GetUserAsync(userId);

            if (toDelete == null)
            {
                // user doesn't exist
                return(false);
            }

            if (toDelete.NickName == "Admin")
            {
                // can't delete admin
                return(false);
            }

            using (var adapter = new DataAccessAdapter())
            {
                await adapter.StartTransactionAsync(IsolationLevel.ReadCommitted, "DeleteUser").ConfigureAwait(false);

                try
                {
                    // we'll first update all PostedByUserId fields of all messages which are posted by the user to delete.
                    var messageUpdater = new MessageEntity {
                        PostedByUserID = 0
                    };

                    // reset to AC.
                    await adapter.UpdateEntitiesDirectlyAsync(messageUpdater, new RelationPredicateBucket(MessageFields.PostedByUserID.Equal(userId)))
                    .ConfigureAwait(false);

                    // set the startuser of threads started by this user to 0
                    var threadUpdater = new ThreadEntity {
                        StartedByUserID = 0
                    };
                    await adapter.UpdateEntitiesDirectlyAsync(threadUpdater, new RelationPredicateBucket(ThreadFields.StartedByUserID.Equal(userId)))
                    .ConfigureAwait(false);

                    // remove the user from the UserRoles set, as the user shouldn't be in any roles.
                    await adapter.DeleteEntitiesDirectlyAsync(typeof(RoleUserEntity), new RelationPredicateBucket(RoleUserFields.UserID.Equal(userId)))
                    .ConfigureAwait(false);

                    // delete all bookmarks of user
                    await adapter.DeleteEntitiesDirectlyAsync(typeof(BookmarkEntity), new RelationPredicateBucket(BookmarkFields.UserID.Equal(userId)))
                    .ConfigureAwait(false);

                    // delete all audit data
                    // first fetch it, then delete all entities from the collection, as the audit data is in an inheritance hierarchy of TargetPerEntity which can't
                    // be deleted directly from the db.
                    var auditData = await adapter.FetchQueryAsync(new QueryFactory().User.Where(UserFields.UserID.Equal(userId))).ConfigureAwait(false);

                    await adapter.DeleteEntityCollectionAsync(auditData).ConfigureAwait(false);

                    // set IP bans set by this user to userid 0
                    var ipbanUpdater = new IPBanEntity {
                        IPBanSetByUserID = 0
                    };
                    await adapter.UpdateEntitiesDirectlyAsync(ipbanUpdater, new RelationPredicateBucket(IPBanFields.IPBanSetByUserID.Equal(userId)))
                    .ConfigureAwait(false);

                    // delete threadsubscriptions
                    await adapter.DeleteEntitiesDirectlyAsync(typeof(ThreadSubscriptionEntity), new RelationPredicateBucket(ThreadSubscriptionFields.UserID.Equal(userId)))
                    .ConfigureAwait(false);

                    // remove supportqueuethread claims
                    await adapter.DeleteEntitiesDirectlyAsync(typeof(SupportQueueThreadEntity),
                                                              new RelationPredicateBucket(SupportQueueThreadFields.ClaimedByUserID.Equal(userId)))
                    .ConfigureAwait(false);

                    // set all placed in queue references to userid 0, so the threads stay in the queues.
                    var supportQueueThreadUpdater = new SupportQueueThreadEntity {
                        PlacedInQueueByUserID = 0
                    };
                    await adapter.UpdateEntitiesDirectlyAsync(supportQueueThreadUpdater,
                                                              new RelationPredicateBucket(SupportQueueThreadFields.PlacedInQueueByUserID.Equal(userId)))
                    .ConfigureAwait(false);

                    // now delete the actual user entity
                    await adapter.DeleteEntityAsync(toDelete).ConfigureAwait(false);

                    adapter.Commit();
                    return(true);
                }
                catch
                {
                    adapter.Rollback();
                    throw;
                }
            }
        }
コード例 #9
0
ファイル: UserManager.cs プロジェクト: priaonehaha/HnD
        /// <summary>
        /// Deletes the user with the ID passed in. Will reset all posts made by the user to the userid 0.
        /// </summary>
        /// <param name="userID">The user ID.</param>
        /// <remarks>Can't delete user 0</remarks>
        /// <returns>true if succeeded, false otherwise</returns>
        public static bool DeleteUser(int userID)
        {
            if (userID == 0)
            {
                // can't delete the Anonymous coward user.
                return(false);
            }

            UserEntity toDelete = UserGuiHelper.GetUser(userID);

            if (toDelete == null)
            {
                // user doesn't exist
                return(false);
            }

            // all actions have to take place in a transaction.
            Transaction trans = new Transaction(IsolationLevel.ReadCommitted, "DeleteUser");

            try
            {
                // we'll first update all PostedByUserId fields of all messages which are posted by the user to delete.
                MessageEntity messageUpdater = new MessageEntity();
                messageUpdater.PostedByUserID = 0;      // reset to AC.
                MessageCollection messages = new MessageCollection();
                trans.Add(messages);                    // add to the transaction
                // update all entities directly in the DB, which match the following filter and update them with the new values set in messageUpdater.
                messages.UpdateMulti(messageUpdater, (MessageFields.PostedByUserID == userID));

                // set the startuser of threads started by this user to 0
                ThreadEntity threadUpdater = new ThreadEntity();
                threadUpdater.StartedByUserID = 0;
                ThreadCollection threads = new ThreadCollection();
                trans.Add(threads);
                threads.UpdateMulti(threadUpdater, (ThreadFields.StartedByUserID == userID));

                // remove the user from the UserRoles set, as the user shouldn't be in any roles.
                RoleUserCollection roleUsersDeleter = new RoleUserCollection();
                trans.Add(roleUsersDeleter);
                // delete all entities directly from the DB which match the following filter.
                roleUsersDeleter.DeleteMulti(RoleUserFields.UserID == userID);

                // delete all bookmarks of user
                BookmarkCollection bookmarkDeleter = new BookmarkCollection();
                trans.Add(bookmarkDeleter);
                // delete all bookmarks for this user directly from the DB using the following filter.
                bookmarkDeleter.DeleteMulti(BookmarkFields.UserID == userID);

                // delete all audit data
                AuditDataCoreCollection auditDataDeleter = new AuditDataCoreCollection();
                // first fetch it, then delete all entities from the collection, as the audit data is in an inheritance hierarchy of TargetPerEntity which can't
                // be deleted directly from the db.
                trans.Add(auditDataDeleter);
                auditDataDeleter.GetMulti(AuditDataCoreFields.UserID == userID);
                auditDataDeleter.DeleteMulti();

                // set IP bans set by this user to userid 0
                IPBanEntity ipbanUpdater = new IPBanEntity();
                ipbanUpdater.IPBanSetByUserID = 0;
                IPBanCollection ipBans = new IPBanCollection();
                trans.Add(ipBans);
                ipBans.UpdateMulti(ipbanUpdater, (IPBanFields.IPBanSetByUserID == userID));

                // delete threadsubscriptions
                ThreadSubscriptionCollection threadSubscriptionsDeleter = new ThreadSubscriptionCollection();
                trans.Add(threadSubscriptionsDeleter);
                threadSubscriptionsDeleter.DeleteMulti(ThreadSubscriptionFields.UserID == userID);

                // remove supportqueuethread claims
                SupportQueueThreadCollection supportQueueThreads = new SupportQueueThreadCollection();
                trans.Add(supportQueueThreads);
                supportQueueThreads.DeleteMulti(SupportQueueThreadFields.ClaimedByUserID == userID);

                // set all placed in queue references to userid 0, so the threads stay in the queues.
                SupportQueueThreadEntity supportQueueThreadUpdater = new SupportQueueThreadEntity();
                supportQueueThreadUpdater.PlacedInQueueByUserID = 0;
                supportQueueThreads.UpdateMulti(supportQueueThreadUpdater, (SupportQueueThreadFields.PlacedInQueueByUserID == userID));

                // now delete the actual user entity
                trans.Add(toDelete);
                toDelete.Delete();

                // all done
                trans.Commit();
                return(true);
            }
            catch
            {
                trans.Rollback();
                throw;
            }
            finally
            {
                trans.Dispose();
            }
        }
コード例 #10
0
ファイル: Messages.aspx.cs プロジェクト: priaonehaha/HnD
        /// <summary>
        /// Handles the Load event of the Page control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void Page_Load(object sender, System.EventArgs e)
        {
            int threadID = HnDGeneralUtils.TryConvertToInt(Request.QueryString["ThreadID"]);

            _thread = ThreadGuiHelper.GetThread(threadID);
            if (_thread == null)
            {
                // not found, return to start page
                Response.Redirect("default.aspx");
            }

            // Check credentials
            bool userHasAccess = SessionAdapter.CanPerformForumActionRight(_thread.ForumID, ActionRights.AccessForum);

            if (!userHasAccess)
            {
                // doesn't have access to this forum. redirect
                Response.Redirect("default.aspx");
            }

            _startMessageNo = HnDGeneralUtils.TryConvertToInt(Request.QueryString["StartAtMessage"]);
            bool highLightSearchResults = (HnDGeneralUtils.TryConvertToInt(Request.QueryString["HighLight"]) == 1);

            if (!_thread.IsClosed)
            {
                if (_thread.IsSticky)
                {
                    _userMayAddNewMessages = SessionAdapter.CanPerformForumActionRight(_thread.ForumID, ActionRights.AddAndEditMessageInSticky);
                }
                else
                {
                    _userMayAddNewMessages = SessionAdapter.CanPerformForumActionRight(_thread.ForumID, ActionRights.AddAndEditMessage);
                }
                // set show*link class members. These have to be set despite the postback status, as they're used in the repeater. Only set
                // them to true if the thread isn't closed. They've been initialized to false already.
                _showEditMessageLink   = SessionAdapter.CanPerformForumActionRight(_thread.ForumID, ActionRights.EditDeleteOtherUsersMessages);
                _showDeleteMessageLink = _showEditMessageLink;
                _showQuoteMessageLink  = _userMayAddNewMessages;
            }

            // show user IP addresses if the user has system admin rights, security admin rights or user admin rights.
            _showIPAddresses = (SessionAdapter.HasSystemActionRight(ActionRights.SystemManagement) ||
                                SessionAdapter.HasSystemActionRight(ActionRights.SecurityManagement) ||
                                SessionAdapter.HasSystemActionRight(ActionRights.UserManagement));
            // Get the forum entity related to the thread. Use BL class. We could have used Lazy loading, though for the sake of separation, we'll
            // call into the BL class.
            ForumEntity forum = CacheManager.GetForum(_thread.ForumID);

            if (forum == null)
            {
                // not found, orphaned thread, return to default page.
                Response.Redirect("default.aspx");
            }
            _forumAllowsAttachments = (forum.MaxNoOfAttachmentsPerMessage > 0);

            // check if the user can view this thread. If not, don't continue.
            if ((_thread.StartedByUserID != SessionAdapter.GetUserID()) &&
                !SessionAdapter.CanPerformForumActionRight(_thread.ForumID, ActionRights.ViewNormalThreadsStartedByOthers) &&
                !_thread.IsSticky)
            {
                // can't view this thread, it isn't visible to the user
                Response.Redirect("default.aspx", true);
            }

            _threadStartedByCurrentUser = (_thread.StartedByUserID == SessionAdapter.GetUserID());
            _userMayAddAttachments      = SessionAdapter.CanPerformForumActionRight(_thread.ForumID, ActionRights.AddAttachment);
            _userCanCreateThreads       = SessionAdapter.CanPerformForumActionRight(_thread.ForumID, ActionRights.AddNormalThread) ||
                                          SessionAdapter.CanPerformForumActionRight(_thread.ForumID, ActionRights.AddStickyThread);
            _userMayDoForumSpecificThreadManagement = SessionAdapter.CanPerformForumActionRight(_thread.ForumID, ActionRights.ForumSpecificThreadManagement);
            _userMayDoSystemWideThreadManagement    = SessionAdapter.HasSystemActionRight(ActionRights.SystemWideThreadManagement);
            _userMayEditMemo                   = SessionAdapter.CanPerformForumActionRight(_thread.ForumID, ActionRights.EditThreadMemo);
            _userMayMarkThreadAsDone           = (SessionAdapter.CanPerformForumActionRight(_thread.ForumID, ActionRights.FlagThreadAsDone) || _threadStartedByCurrentUser);
            _userMayManageSupportQueueContents = SessionAdapter.HasSystemActionRight(ActionRights.QueueContentManagement);
            _userMayDoBasicThreadOperations    = (SessionAdapter.GetUserID() > 0);

            if (!Page.IsPostBack)
            {
                plPageListBottom.HighLight = highLightSearchResults;
                plPageListTop.HighLight    = highLightSearchResults;
                litHighLightLogic.Visible  = highLightSearchResults;

                if (highLightSearchResults)
                {
                    // make highlighting of search results possible
                    string searchTerms = SessionAdapter.GetSearchTerms();
                    if (searchTerms == null)
                    {
                        searchTerms = string.Empty;
                    }
                    this.ClientScript.RegisterHiddenField("searchTerms", searchTerms.Replace("AND", "").Replace("OR", "").Replace("and", "").Replace("or", "").Replace("\"", ""));
                }
                else
                {
                    // replace hightlighting scriptblock.
                    this.ClientScript.RegisterClientScriptBlock(this.GetType(), "onLoad", "<script language=\"javascript\"  type=\"text/javascript\">function SearchHighlight() {}</script>");
                }

                if (_userMayManageSupportQueueContents)
                {
                    // fill support queue management area with data.
                    SupportQueueCollection supportQueues = CacheManager.GetAllSupportQueues();
                    cbxSupportQueues.DataSource = supportQueues;
                    cbxSupportQueues.DataBind();

                    SupportQueueEntity containingQueue = SupportQueueGuiHelper.GetQueueOfThread(_thread.ThreadID);
                    if (containingQueue != null)
                    {
                        cbxSupportQueues.SelectedValue = containingQueue.QueueID.ToString();
                        // get claim info
                        SupportQueueThreadEntity supportQueueThreadInfo = SupportQueueGuiHelper.GetSupportQueueThreadInfo(_thread.ThreadID, true);
                        if ((supportQueueThreadInfo != null) && supportQueueThreadInfo.ClaimedByUserID.HasValue)
                        {
                            // claimed by someone
                            lblClaimDate.Text             = supportQueueThreadInfo.ClaimedOn.Value.ToString("dd-MMM-yyyy HH:mm.ss", DateTimeFormatInfo.InvariantInfo);
                            lnkClaimerThread.Visible      = true;
                            lblNotClaimed.Visible         = false;
                            lnkClaimerThread.Text         = supportQueueThreadInfo.ClaimedByUser.NickName;
                            lnkClaimerThread.NavigateUrl += supportQueueThreadInfo.ClaimedByUserID.ToString();
                            btnClaim.Visible              = false;
                            btnRelease.Visible            = true;
                        }
                        else
                        {
                            // not claimed
                            lblClaimDate.Text  = string.Empty;
                            btnClaim.Visible   = true;
                            btnRelease.Visible = false;
                        }
                    }
                }
                phSupportQueueManagement.Visible = _userMayManageSupportQueueContents;

                if ((_thread.Memo.Length > 0) && _userMayEditMemo)
                {
                    // convert memo contents to HTML so it's displayed above the thread.
                    string parserLog, messageTextXml;
                    bool   errorsOccured = false;
                    string memoAsHTML    = TextParser.TransformUBBMessageStringToHTML(_thread.Memo, ApplicationAdapter.GetParserData(), out parserLog, out errorsOccured, out messageTextXml);
                    lblMemo.Text = memoAsHTML;
                }
                phMemo.Visible = _userMayEditMemo;

                bool isBookmarked = UserGuiHelper.CheckIfThreadIsAlreadyBookmarked(SessionAdapter.GetUserID(), threadID);
                bool isSubscribed = UserGuiHelper.CheckIfThreadIsAlreadySubscribed(SessionAdapter.GetUserID(), threadID);
                btnBookmarkThread.Visible   = !isBookmarked && _userMayDoBasicThreadOperations;
                btnUnbookmarkThread.Visible = isBookmarked && _userMayDoBasicThreadOperations;
                bool sendReplyNotifications = CacheManager.GetSystemData().SendReplyNotifications;
                btnSubscribeToThread.Visible     = !isSubscribed && _userMayDoBasicThreadOperations && sendReplyNotifications;
                btnUnsubscribeFromThread.Visible = isSubscribed && _userMayDoBasicThreadOperations && sendReplyNotifications;

                // fill the page's content
                lnkThreads.Text          = HttpUtility.HtmlEncode(forum.ForumName);
                lnkThreads.NavigateUrl  += "?ForumID=" + _thread.ForumID;
                lblForumName_Header.Text = forum.ForumName;
                lblSectionName.Text      = CacheManager.GetSectionName(forum.SectionID);

                // Check if the current user is allowed to add new messages to the thread.

                // these controls are not visible by default, show them if necessary
                if (_userMayDoForumSpecificThreadManagement || _userMayDoSystemWideThreadManagement)
                {
                    if (!_thread.IsClosed && _userMayAddNewMessages)
                    {
                        lnkCloseThread.Visible      = true;
                        lnkCloseThread.NavigateUrl += "?ThreadID=" + threadID + "&StartAtMessage=" + _startMessageNo;
                    }
                    lnkEditThreadProperties.Visible      = true;
                    lnkEditThreadProperties.NavigateUrl += "?ThreadID=" + threadID;
                }

                if (_userMayDoSystemWideThreadManagement)
                {
                    lnkMoveThread.Visible        = true;
                    lnkMoveThread.NavigateUrl   += "?ThreadID=" + threadID;
                    lnkDeleteThread.Visible      = true;
                    lnkDeleteThread.NavigateUrl += "?ThreadID=" + threadID;
                }

                btnThreadDone.Visible    = _thread.MarkedAsDone;
                btnThreadNotDone.Visible = !_thread.MarkedAsDone;
                btnThreadDone.Enabled    = _userMayMarkThreadAsDone;
                btnThreadNotDone.Enabled = _userMayMarkThreadAsDone;

                if (_userMayEditMemo)
                {
                    lnkEditMemo.Visible      = true;
                    lnkEditMemo.NavigateUrl += "?ThreadID=" + threadID + "&StartAtMessage=" + _startMessageNo;
                }

                // These controls are visible by default. Hide them when the user can't create threads on this forum
                if (_userCanCreateThreads)
                {
                    lnkNewThreadBottom.NavigateUrl += "?ForumID=" + _thread.ForumID + "&StartAtMessage=" + _startMessageNo;
                    lnkNewThreadTop.NavigateUrl    += "?ForumID=" + _thread.ForumID + "&StartAtMessage=" + _startMessageNo;
                }
                else
                {
                    lnkNewThreadBottom.Visible = false;
                    lnkNewThreadTop.Visible    = false;
                }

                if (_userMayAddNewMessages)
                {
                    lnkNewMessageBottom.NavigateUrl += "?ThreadID=" + threadID + "&StartAtMessage=" + _startMessageNo;
                    lnkNewMessageTop.NavigateUrl    += "?ThreadID=" + threadID + "&StartAtMessage=" + _startMessageNo;
                }
                else
                {
                    lnkNewMessageBottom.Visible = false;
                    lnkNewMessageTop.Visible    = false;
                }
                lblSeparatorTop.Visible    = (_userMayAddNewMessages && _userCanCreateThreads);
                lblSeparatorBottom.Visible = (_userMayAddNewMessages && _userCanCreateThreads);

                // The amount of postings in this thread are in the dataview row, which should contain just 1 row.
                int maxAmountMessagesPerPage = SessionAdapter.GetUserDefaultNumberOfMessagesPerPage();
                int amountOfMessages         = ThreadGuiHelper.GetTotalNumberOfMessagesInThread(threadID);
                int amountOfPages            = ((amountOfMessages - 1) / maxAmountMessagesPerPage) + 1;
                int currentPageNo            = (_startMessageNo / maxAmountMessagesPerPage) + 1;
                lblCurrentPage.Text = currentPageNo.ToString();
                lblTotalPages.Text  = amountOfPages.ToString();

                lnkPrintThread.NavigateUrl += "?ThreadID=" + threadID;

                plPageListBottom.AmountMessages = amountOfMessages;
                plPageListBottom.StartMessageNo = _startMessageNo;
                plPageListBottom.ThreadID       = threadID;
                plPageListTop.AmountMessages    = amountOfMessages;
                plPageListTop.StartMessageNo    = _startMessageNo;
                plPageListTop.ThreadID          = threadID;

                // Get messages and bind it to the repeater control. Use the startmessage to get only the message visible on the current page.
                MessagesInThreadTypedList messages = ThreadGuiHelper.GetAllMessagesInThreadAsTypedList(threadID, currentPageNo, maxAmountMessagesPerPage);
                rptMessages.DataSource = messages;
                rptMessages.DataBind();
            }
        }