/// <summary> /// Gets the name of the tab. /// </summary> /// <param name="tabName"></param> /// <param name="tabValue"></param> /// <returns></returns> private string GetTabName(string tabName, string tabValue) { switch (tabValue.ToLower()) { case "tabcomments": return(string.Format("{0} ({1})", tabName, IssueId == 0 ? 0 : IssueCommentManager.GetByIssueId(IssueId).Count)); case "tabhistory": return(string.Format("{0} ({1})", tabName, IssueId == 0 ? 0 : IssueHistoryManager.GetByIssueId(IssueId).Count)); case "tabattachments": return(string.Format("{0} ({1})", tabName, IssueId == 0 ? 0 : IssueAttachmentManager.GetByIssueId(IssueId).Count)); case "tabnotifications": return(string.Format("{0} ({1})", tabName, IssueId == 0 ? 0 : IssueNotificationManager.GetByIssueId(IssueId).Count)); case "tabrelatedissues": return(string.Format("{0} ({1})", tabName, IssueId == 0 ? 0 : RelatedIssueManager.GetRelatedIssues(IssueId).Count)); case "tabparentissues": return(string.Format("{0} ({1})", tabName, IssueId == 0 ? 0 : RelatedIssueManager.GetParentIssues(IssueId).Count)); case "tabsubissues": return(string.Format("{0} ({1})", tabName, IssueId == 0 ? 0 : RelatedIssueManager.GetChildIssues(IssueId).Count)); case "tabrevisions": return(string.Format("{0} ({1})", tabName, IssueId == 0 ? 0 : IssueRevisionManager.GetByIssueId(IssueId).Count)); case "tabtimetracking": return(string.Format("{0} ({1})", tabName, IssueId == 0 ? 0 : IssueWorkReportManager.GetByIssueId(IssueId).Count)); default: return(tabName); } }
/// <summary> /// Handles the ItemDataBound event of the IssuesCommentListRepeater control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.Web.UI.WebControls.RepeaterItemEventArgs"/> instance containing the event data.</param> protected void IssuesCommentListRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e) { if (e.Item.ItemType != ListItemType.Item && e.Item.ItemType != ListItemType.AlternatingItem) { return; } var lblcomm = ((Label)e.Item.FindControl("lblComment")); var ic = (IssueComment)e.Item.DataItem; // Prevent XSS lblcomm.Text = Server.HtmlEncode(IssueCommentManager.GetShortTextComment(ic.Comment)); }
/// <summary> /// Gets the name of the tab. /// </summary> /// <param name="tabName"></param> /// <param name="tabValue"></param> /// <returns></returns> private string GetTabName(string tabName, string tabValue) { int cnt; switch (tabValue.ToLower()) { case "tabcomments": cnt = IssueId == 0 ? 0 : IssueCommentManager.GetByIssueId(IssueId).Count; return(string.Format("<span class='{2}'>{0} ({1})</span>", tabName, cnt, cnt == 0 ? "normal" : "bold")); case "tabhistory": cnt = IssueId == 0 ? 0 : IssueHistoryManager.GetByIssueId(IssueId).Count; return(string.Format("<span class='{2}'>{0} ({1})</span>", tabName, cnt, cnt == 0 ? "normal" : "normal")); case "tabattachments": cnt = IssueId == 0 ? 0 : IssueAttachmentManager.GetByIssueId(IssueId).Count; return(string.Format("<span class='{2}'>{0} ({1})</span>", tabName, cnt, cnt == 0 ? "normal" : "bold")); case "tabnotifications": cnt = IssueId == 0 ? 0 : IssueNotificationManager.GetByIssueId(IssueId).Count; return(string.Format("<span class='{2}'>{0} ({1})</span>", tabName, cnt, cnt == 0 ? "normal" : "normal")); case "tabrelatedissues": cnt = IssueId == 0 ? 0 : RelatedIssueManager.GetRelatedIssues(IssueId).Count; return(string.Format("<span class='{2}'>{0} ({1})</span>", tabName, cnt, cnt == 0 ? "normal" : "bold")); case "tabparentissues": cnt = IssueId == 0 ? 0 : RelatedIssueManager.GetParentIssues(IssueId).Count; return(string.Format("<span class='{2}'>{0} ({1})</span>", tabName, cnt, cnt == 0 ? "normal" : "bold")); case "tabsubissues": cnt = IssueId == 0 ? 0 : RelatedIssueManager.GetChildIssues(IssueId).Count; return(string.Format("<span class='{2}'>{0} ({1})</span>", tabName, cnt, cnt == 0 ? "normal" : "bold")); case "tabrevisions": cnt = IssueId == 0 ? 0 : IssueRevisionManager.GetByIssueId(IssueId).Count; return(string.Format("<span class='{2}'>{0} ({1})</span>", tabName, cnt, cnt == 0 ? "normal" : "normal")); case "tabtimetracking": cnt = IssueId == 0 ? 0 : IssueWorkReportManager.GetByIssueId(IssueId).Count; return(string.Format("<span class='{2}'>{0} ({1})</span>", tabName, cnt, cnt == 0 ? "normal" : "normal")); default: return(tabName); } }
/// <summary> /// Binds the comments. /// </summary> private void BindComments() { IList comments = IssueCommentManager.GetByIssueId(IssueId); if (comments.Count == 0) { lblComments.Text = GetLocalResourceObject("NoComments").ToString(); lblComments.Visible = true; rptComments.Visible = false; } else { _issueOwnerUserId = IssueManager.GetById(IssueId).OwnerUserId; lblComments.Visible = false; rptComments.DataSource = comments; rptComments.DataBind(); rptComments.Visible = true; } }
/// <summary> /// Handles the Click event of the cmdAddComment 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> protected void CmdAddCommentClick(object sender, EventArgs e) { if (CommentHtmlEditor.Text.Trim().Length == 0) { return; } var comment = new IssueComment { IssueId = IssueId, Comment = CommentHtmlEditor.Text.Trim(), CreatorUserName = Security.GetUserName(), DateCreated = DateTime.Now }; var result = IssueCommentManager.SaveOrUpdate(comment); if (result) { //add history record var history = new IssueHistory { IssueId = IssueId, CreatedUserName = Security.GetUserName(), DateChanged = DateTime.Now, FieldChanged = ResourceStrings.GetGlobalResource(GlobalResources.SharedResources, "Comment", "Comment"), OldValue = string.Empty, NewValue = ResourceStrings.GetGlobalResource(GlobalResources.SharedResources, "Added", "Added"), TriggerLastUpdateChange = true }; IssueHistoryManager.SaveOrUpdate(history); } CommentHtmlEditor.Text = String.Empty; BindComments(); }
/// <summary> /// Performs the issue search and populates mainIssues and mainComment. /// </summary> /// <param name="searchProjects">A List of projects to search through.</param> private void PerformIssueSearch(IEnumerable <Project> searchProjects) { var foundComments = new List <IssueComment>(); var issueComments = new List <IssueComment>(); // Our search strings on normal and "like" comparators // Note: these are deliberately not trimmed! // to the users, "test" might be different from "test " var strSearch = txtSearch.Text; var strLike = "%" + strSearch + "%"; var strHtmlSearch = Server.HtmlEncode(strSearch); var strHtmlLike = "%" + strHtmlSearch + "%"; // if the two strings are equal srchHtmlcode is false // If they are not equal, then I need to search for the HTML encoded // variants later on. var srchHtmlcode = strHtmlSearch != strSearch; var srchComments = chkComments.Checked; // Sort the projects using LINQ foreach (var p in searchProjects) { // now search each project with wildcard parameters // (except for the search string) // --------------------------------------------------------------- // Normal Search // // Searches Description, Issue Title using a LIKE query // If you are searching username it adds the LastUpdateUsername, // AssignedUsername, CreatorUserName, OwnerUserName to the list. // // --------------------------------------------------------------- var queryClauses = new List <QueryClause>(); // filter out disabled issues queryClauses.Add(new QueryClause("AND", "iv.[Disabled]", "=", "0", SqlDbType.Int)); // if the user wants to exclude closed issues then filter the closed flag otherwise don't bother if (chkExcludeClosedIssues.Checked) { queryClauses.Add(new QueryClause("AND", "iv.[IsClosed]", "=", "0", SqlDbType.Int)); } queryClauses.Add(new QueryClause("AND (", "1", "=", "2", SqlDbType.NVarChar)); queryClauses.Add(new QueryClause("OR", "iv.[IssueId]", "LIKE", strLike, SqlDbType.NVarChar)); if (chkSearchTitle.Checked || chkSearchDesc.Checked) { if (chkSearchTitle.Checked) { queryClauses.Add(new QueryClause("OR", "iv.[IssueTitle]", "LIKE", strLike, SqlDbType.NVarChar)); if (srchHtmlcode) { queryClauses.Add(new QueryClause("OR", "iv.[IssueTitle]", "LIKE", strHtmlLike, SqlDbType.NVarChar)); } } if (chkSearchDesc.Checked) { queryClauses.Add(new QueryClause("OR", "iv.[IssueDescription]", "LIKE", strLike, SqlDbType.NVarChar)); if (srchHtmlcode) { queryClauses.Add(new QueryClause("OR", "iv.[IssueDescription]", "LIKE", strHtmlLike, SqlDbType.NVarChar)); } } } queryClauses.Add(new QueryClause(")", "", "", "", SqlDbType.NVarChar)); // Use the new Generic way to search with those QueryClauses var issues = IssueManager.PerformQuery(queryClauses, null, p.Id); queryClauses.Clear(); _mainIssues.AddRange(issues); // --------------------------------------------------------------- // Search Comments // // --------------------------------------------------------------- if (!srchComments) { continue; } issues.Clear(); issueComments.Clear(); foundComments.Clear(); queryClauses.Add(new QueryClause("AND", "iv.[Disabled]", "=", "0", SqlDbType.Int)); // if the user wants to exclude closed issues then filter the closed flag otherwise don't bother // stuff the criteria into the first spot because we have an open nested criteria going on if (chkExcludeClosedIssues.Checked) { queryClauses.Insert(0, new QueryClause("AND", "iv.[IsClosed]", "=", "0", SqlDbType.Int)); } // Get ALL issues issues = IssueManager.PerformQuery(queryClauses, null, p.Id); // to the private check on all issues issues = IssueManager.StripPrivateIssuesForRequestor(issues, Security.GetUserName()).ToList(); foreach (var iss in issues) { // New Way // Using the Generic Interface var qryComment = new List <QueryClause> { new QueryClause("AND (", "Comment", "LIKE", strLike, SqlDbType.NVarChar) }; if (srchHtmlcode) { qryComment.Add(new QueryClause("OR", "Comment", "LIKE", strHtmlLike, SqlDbType.NVarChar)); } // close parenthesis qryComment.Add(new QueryClause(")", "", "", "", SqlDbType.NVarChar)); issueComments = IssueCommentManager.PerformQuery(iss.Id, qryComment); // Did we find anything? if (issueComments.Count <= 0) { continue; } _mainComments.AddRange(issueComments); _mainIssues.Add(iss); // make sure we record the parent issue of the comment(s) } } // --------------------------------------------------------------- // Clean up duplicates and sort // // mainIssues and mainComments // Sorry for the horrible variable names // // --------------------------------------------------------------- var tmpIss = (from iss1 in _mainIssues orderby iss1.ProjectId, iss1.Id descending select iss1).Distinct(new DistinctIssueComparer()); var tmpIssues1 = new List <Issue>(); tmpIssues1.AddRange(tmpIss); _mainIssues.Clear(); _mainIssues.AddRange(tmpIssues1); // to the private check on all issues _mainIssues = IssueManager.StripPrivateIssuesForRequestor(_mainIssues, Security.GetUserName()).ToList(); // mainIssues list should be pure now var tmpComm = (from comm in _mainComments orderby comm.IssueId, comm.Id select comm) .Distinct(); var tmpComm1 = new List <IssueComment>(); tmpComm1.AddRange(tmpComm); _mainComments.Clear(); _mainComments.AddRange(tmpComm1); }
/// <summary> /// Handles the ItemCommand event of the rptComments control. /// </summary> /// <param name="source">The source of the event.</param> /// <param name="e">The <see cref="System.Web.UI.WebControls.RepeaterCommandEventArgs"/> instance containing the event data.</param> protected void RptCommentsItemCommand(object source, RepeaterCommandEventArgs e) { var pnlEditComment = e.Item.FindControl("pnlEditComment") as Panel; var pnlComment = e.Item.FindControl("pnlComment") as Panel; if (pnlEditComment == null) { return; } if (pnlComment == null) { return; } BugNET.UserControls.HtmlEditor editor; HiddenField commentNumber; IssueComment comment; switch (e.CommandName) { case "Save": editor = pnlEditComment.FindControl("EditCommentHtmlEditor") as BugNET.UserControls.HtmlEditor; if (editor != null) { if (editor.Text.Trim().Length == 0) { return; } commentNumber = (HiddenField)pnlEditComment.FindControl("commentNumber"); var commentId = Convert.ToInt32(commentNumber.Value); comment = IssueCommentManager.GetById(Convert.ToInt32(commentId)); comment.Comment = editor.Text.Trim(); IssueCommentManager.SaveOrUpdate(comment); editor.Text = String.Empty; commentNumber.Value = String.Empty; } pnlEditComment.Visible = false; pnlComment.Visible = true; pnlAddComment.Visible = true; BindComments(); break; case "Cancel": pnlEditComment.Visible = false; pnlComment.Visible = true; pnlAddComment.Visible = true; BindComments(); break; case "Delete": IssueCommentManager.Delete(Convert.ToInt32(e.CommandArgument)); BindComments(); break; case "Edit": comment = IssueCommentManager.GetById(Convert.ToInt32(e.CommandArgument)); // Show the edit comment panel for the comment pnlAddComment.Visible = false; pnlEditComment.Visible = true; pnlComment.Visible = false; // Insert the existing comment text in the edit control. editor = pnlEditComment.FindControl("EditCommentHtmlEditor") as BugNET.UserControls.HtmlEditor; if (editor != null) { editor.Text = comment.Comment; } // Save the comment ID for further editting. commentNumber = (HiddenField)e.Item.FindControl("commentNumber"); if (commentNumber != null) { commentNumber.Value = (string)e.CommandArgument; } break; } }
private bool ProcessNewComment(List <string> recipients, POP3_ClientMessage message, Mail_Message mailHeader, MailboxReaderResult result) { string messageFrom = string.Empty; if (mailHeader.From.Count > 0) { messageFrom = string.Join("; ", mailHeader.From.ToList().Select(p => p.Address).ToArray()).Trim(); } bool processed = false; foreach (var address in recipients) { Regex isReply = new Regex(@"(.*)(\+iid-)(\d+)@(.*)"); Match commentMatch = isReply.Match(address); if (commentMatch.Success && commentMatch.Groups.Count >= 4) { // we are in a reply and group 4 must contain the id of the original issue int issueId; if (int.TryParse(commentMatch.Groups[3].Value, out issueId)) { var _currentIssue = IssueManager.GetById(issueId); if (_currentIssue != null) { var project = ProjectManager.GetById(_currentIssue.ProjectId); var mailbody = Mail_Message.ParseFromByte(message.MessageToByte()); bool isHtml; List <MIME_Entity> attachments = null; string content = GetMessageContent(mailbody, project, out isHtml, ref attachments); IssueComment comment = new IssueComment { IssueId = issueId, Comment = content, DateCreated = mailHeader.Date }; // try to find if the creator is valid user in the project, otherwise take // the user defined in the mailbox config var users = UserManager.GetUsersByProjectId(project.Id); var emails = messageFrom.Split(';').Select(e => e.Trim().ToLower()); var user = users.Find(x => emails.Contains(x.Email.ToLower())); if (user != null) { comment.CreatorUserName = user.UserName; } else { // user not found continue; } var saved = IssueCommentManager.SaveOrUpdate(comment); if (saved) { //add history record var history = new IssueHistory { IssueId = issueId, CreatedUserName = comment.CreatorUserName, DateChanged = comment.DateCreated, FieldChanged = ResourceStrings.GetGlobalResource(GlobalResources.SharedResources, "Comment", "Comment"), OldValue = string.Empty, NewValue = ResourceStrings.GetGlobalResource(GlobalResources.SharedResources, "Added", "Added"), TriggerLastUpdateChange = true }; IssueHistoryManager.SaveOrUpdate(history); var projectFolderPath = Path.Combine(Config.UploadsFolderPath, project.UploadPath); // save attachments as new files int attachmentsSavedCount = 1; foreach (MIME_Entity mimeEntity in attachments) { string fileName; var contentType = mimeEntity.ContentType.Type.ToLower(); var attachment = new IssueAttachment { Id = 0, Description = "File attached by mailbox reader", DateCreated = DateTime.Now, ContentType = mimeEntity.ContentType.TypeWithSubtype, CreatorDisplayName = user.DisplayName, CreatorUserName = user.UserName, IssueId = issueId, ProjectFolderPath = projectFolderPath }; attachment.Attachment = ((MIME_b_SinglepartBase)mimeEntity.Body).Data; if (contentType.Equals("attachment")) // this is an attached email { fileName = mimeEntity.ContentDisposition.Param_FileName; } else if (contentType.Equals("message")) // message has no filename so we create one { fileName = string.Format("Attached_Message_{0}.eml", attachmentsSavedCount); } else { fileName = string.IsNullOrWhiteSpace(mimeEntity.ContentType.Param_Name) ? string.Format("untitled.{0}", mimeEntity.ContentType.SubType) : mimeEntity.ContentType.Param_Name; } attachment.FileName = fileName; var saveFile = IsAllowedFileExtension(fileName); var fileSaved = false; // can we save the file? if (saveFile) { fileSaved = IssueAttachmentManager.SaveOrUpdate(attachment); if (fileSaved) { attachmentsSavedCount++; } else { LogWarning("MailboxReader: Attachment could not be saved, please see previous logs"); } } } processed = true; // add the entry if the save did not throw any exceptions result.MailboxEntries.Add(new MailboxEntry()); } } } } } return(processed); }