You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

186 lines
6.5 KiB

  1. using System;
  2. using System.Configuration;
  3. using System.Linq;
  4. using System.Net.Mail;
  5. using System.Text.RegularExpressions;
  6. using System.Web;
  7. using System.Web.WebPages;
  8. public class CommentHandler : IHttpHandler
  9. {
  10. public void ProcessRequest(HttpContext context)
  11. {
  12. Post post = Storage.GetAllPosts().SingleOrDefault(p => p.ID == context.Request["postId"]);
  13. if (post == null)
  14. throw new HttpException(404, "The post does not exist");
  15. string mode = context.Request["mode"];
  16. if (mode == "save" && context.Request.HttpMethod == "POST" && post.AreCommentsOpen(new HttpContextWrapper(context)) && Blog.MatchesUniqueId(context))
  17. {
  18. Save(context, post);
  19. }
  20. else if (mode == "delete")
  21. {
  22. Delete(context, post);
  23. }
  24. else if (mode == "approve")
  25. {
  26. Approve(context, post);
  27. }
  28. }
  29. private static void Save(HttpContext context, Post post)
  30. {
  31. string name = context.Request.Form["name"];
  32. string email = context.Request.Form["email"];
  33. string website = context.Request.Form["website"];
  34. string content = context.Request.Form["content"];
  35. Validate(name, email, content);
  36. Comment comment = new Comment()
  37. {
  38. Author = name.Trim(),
  39. Email = email.Trim(),
  40. Website = GetUrl(website),
  41. Ip = context.Request.UserHostAddress,
  42. UserAgent = context.Request.UserAgent,
  43. IsAdmin = context.User.Identity.IsAuthenticated,
  44. Content = HttpUtility.HtmlEncode(content.Trim()).Replace("\n", "<br />"),
  45. IsApproved = !Blog.ModerateComments,
  46. };
  47. post.Comments.Add(comment);
  48. Storage.Save(post);
  49. if (!context.User.Identity.IsAuthenticated)
  50. System.Threading.ThreadPool.QueueUserWorkItem((s) => SendEmail(comment, post, context.Request));
  51. RenderComment(context, comment);
  52. }
  53. private static void RenderComment(HttpContext context, Comment comment)
  54. {
  55. var page = (WebPage)WebPageBase.CreateInstanceFromVirtualPath("~/themes/" + Blog.Theme + "/comment.cshtml");
  56. page.Context = new HttpContextWrapper(context);
  57. page.ExecutePageHierarchy(new WebPageContext(page.Context, page: null, model: comment), context.Response.Output);
  58. }
  59. private static void SendEmail(Comment comment, Post post, HttpRequest request)
  60. {
  61. try
  62. {
  63. MailMessage mail = new MailMessage();
  64. mail.From = new MailAddress(comment.Email, comment.Author);
  65. mail.ReplyToList.Add(comment.Email);
  66. mail.To.Add(ConfigurationManager.AppSettings.Get("blog:email"));
  67. mail.Subject = "Blog comment: " + post.Title;
  68. mail.IsBodyHtml = true;
  69. string absoluteUrl = request.Url.Scheme + "://" + request.Url.Authority;
  70. string deleteUrl = absoluteUrl + request.RawUrl + "?postId=" + post.ID + "&commentId=" + comment.ID + "&mode=delete";
  71. string approveUrl = absoluteUrl + request.RawUrl + "?postId=" + post.ID + "&commentId=" + comment.ID + "&mode=approve";
  72. mail.Body = "<div style=\"font: 11pt/1.5 calibri, arial;\">" +
  73. comment.Author + " on <a href=\"" + absoluteUrl + post.Url + "\">" + post.Title + "</a>:<br /><br />" +
  74. comment.Content + "<br /><br />" +
  75. (Blog.ModerateComments ? "<a href=\"" + approveUrl + "\">Approve comment</a> | " : string.Empty) +
  76. "<a href=\"" + deleteUrl + "\">Delete comment</a>" +
  77. "<br /><br /><hr />" +
  78. "Website: " + comment.Website + "<br />" +
  79. "E-mail: " + comment.Email + "<br />" +
  80. "IP-address: " + comment.Ip +
  81. "</div>";
  82. SmtpClient client = new SmtpClient();
  83. client.Send(mail);
  84. }
  85. catch
  86. { }
  87. }
  88. private static void Validate(string name, string email, string content)
  89. {
  90. bool isName = !string.IsNullOrEmpty(name);
  91. bool isMail = !string.IsNullOrEmpty(email) && Regex.IsMatch(email, @"^([\w\.\-]+)@([\w\-]+)((\.(\w){2,3})+)$");
  92. bool isContent = !string.IsNullOrEmpty(content);
  93. if (!isName || !isMail || !isContent)
  94. {
  95. if (!isName)
  96. HttpContext.Current.Response.Status = "403 Please enter a valid name";
  97. else if (!isMail)
  98. HttpContext.Current.Response.Status = "403 Please enter a valid e-mail address";
  99. else if (!isContent)
  100. HttpContext.Current.Response.Status = "403 Please enter a valid comment";
  101. HttpContext.Current.Response.End();
  102. }
  103. }
  104. private static string GetUrl(string website)
  105. {
  106. if (!website.Contains("://"))
  107. website = "http://" + website;
  108. Uri url;
  109. if (Uri.TryCreate(website, UriKind.Absolute, out url))
  110. return url.ToString();
  111. return string.Empty;
  112. }
  113. private static void Delete(HttpContext context, Post post)
  114. {
  115. if (!context.User.Identity.IsAuthenticated)
  116. throw new HttpException(403, "No access");
  117. string commentId = context.Request["commentId"];
  118. Comment comment = post.Comments.SingleOrDefault(c => c.ID == commentId);
  119. if (comment != null)
  120. {
  121. post.Comments.Remove(comment);
  122. Storage.Save(post);
  123. }
  124. else
  125. {
  126. throw new HttpException(404, "Comment could not be found");
  127. }
  128. if (context.Request.HttpMethod == "GET")
  129. {
  130. context.Response.Redirect(post.AbsoluteUrl.ToString() + "#comments", true);
  131. }
  132. }
  133. private static void Approve(HttpContext context, Post post)
  134. {
  135. if (!context.User.Identity.IsAuthenticated)
  136. throw new HttpException(403, "No access");
  137. string commentId = context.Request["commentId"];
  138. Comment comment = post.Comments.SingleOrDefault(c => c.ID == commentId);
  139. if (comment != null)
  140. {
  141. comment.IsApproved = true;
  142. Storage.Save(post);
  143. }
  144. else
  145. {
  146. throw new HttpException(404, "Comment could not be found");
  147. }
  148. if (context.Request.HttpMethod == "GET")
  149. {
  150. context.Response.Redirect(post.AbsoluteUrl.ToString() + "#comments", true);
  151. }
  152. }
  153. public bool IsReusable
  154. {
  155. get { return false; }
  156. }
  157. }