public static bool DetectSpam(this Topic topic) { var member = ApplicationContext.Current.Services.MemberService.GetById(topic.MemberId); topic.IsSpam = SpamChecker.IsSpam(member, string.Format("{0} {1}", topic.Title, topic.Body)); return(topic.IsSpam); }
public ExpandoObject Topic(TopicSaveModel model) { dynamic o = new ExpandoObject(); var t = new Topic(); t.Body = model.Body; t.Title = model.Title; t.MemberId = Members.GetCurrentMemberId(); t.Created = DateTime.Now; t.ParentId = model.Forum; t.UrlName = url.FormatUrl(model.Title); t.Updated = DateTime.Now; t.Version = model.Version; t.Locked = false; t.LatestComment = 0; t.LatestReplyAuthor = 0; t.Replies = 0; t.Score = 0; t.Answer = 0; t.LatestComment = 0; t.IsSpam = Members.GetCurrentMember().GetPropertyValue <bool>("blocked") || t.DetectSpam(); TopicService.Save(t); if (t.IsSpam) { SpamChecker.SendSlackSpamReport(t.Body, t.Id, "topic", t.MemberId); } o.url = string.Format("{0}/{1}-{2}", library.NiceUrl(t.ParentId), t.Id, t.UrlName); return(o); }
public static bool DetectSpam(this Comment comment) { var member = ApplicationContext.Current.Services.MemberService.GetById(comment.MemberId); comment.IsSpam = SpamChecker.IsSpam(member, comment.Body); return(comment.IsSpam); }
public ExpandoObject Comment(CommentSaveModel model) { dynamic o = new ExpandoObject(); var currentMemberId = Members.GetCurrentMemberId(); var c = new Comment(); c.Body = model.Body; c.MemberId = currentMemberId; c.Created = DateTime.Now; c.ParentCommentId = model.Parent; c.TopicId = model.Topic; c.IsSpam = Members.GetCurrentMember().GetPropertyValue <bool>("blocked") || c.DetectSpam(); CommentService.Save(c); if (c.IsSpam) { SpamChecker.SendSlackSpamReport(c.Body, c.TopicId, "comment", c.MemberId); } o.id = c.Id; o.body = c.Body.Sanitize().ToString(); o.topicId = c.TopicId; o.authorId = c.MemberId; o.created = c.Created.ConvertToRelativeTime(); var author = Members.GetById(currentMemberId); o.authorKarma = author.Karma(); o.authorName = author.Name; o.roles = author.GetRoles(); o.cssClass = model.Parent > 0 ? "level-2" : string.Empty; o.parent = model.Parent; o.isSpam = c.IsSpam; return(o); }
public ExpandoObject Topic(TopicSaveModel model) { dynamic o = new ExpandoObject(); var t = new Topic(); t.Body = model.Body; t.Title = model.Title; t.MemberId = Members.GetCurrentMemberId(); t.Created = DateTime.Now; t.ParentId = model.Forum; t.UrlName = url.FormatUrl(model.Title); t.Updated = DateTime.Now; t.Version = model.Version; t.Locked = false; t.LatestComment = 0; t.LatestReplyAuthor = 0; t.Replies = 0; t.Score = 0; t.Answer = 0; t.LatestComment = 0; t.IsSpam = Members.GetCurrentMember().GetPropertyValue <bool>("blocked") || t.DetectSpam(); // If the chosen version is Umbraco Heartcore, overrule other categories if (model.Version == Constants.Forum.HeartcoreVersionNumber) { var heartCodeForumId = GetForumIdFromName(Constants.Forum.UmbracoHeadlessName); t.ParentId = heartCodeForumId; } // If the chosen version is Umbraco Uno, overrule other categories if (model.Version == Constants.Forum.UnoVersionNumber) { var heartCodeForumId = GetForumIdFromName(Constants.Forum.UmbracoUnoName); t.ParentId = heartCodeForumId; } // If the chosen version is Umbraco 9, overrule other categories if (model.Version == 9) { var heartCodeForumId = GetForumIdFromName("Umbraco 9"); t.ParentId = heartCodeForumId; } TopicService.Save(t); if (t.IsSpam) { SpamChecker.SendSlackSpamReport(t.Body, t.Id, "topic", t.MemberId); } o.url = string.Format("{0}/{1}-{2}", library.NiceUrl(t.ParentId), t.Id, t.UrlName); return(o); }
public ActionResult Page(PageName page, PageModel model) { var entry = Repository.FindFirstOrDefault(new EntryByNameQuery(page)); if (entry == null) { return(RedirectToAction("Recent")); } if (!ModelState.IsValid) { model.Entry = entry; model.Page = page; ViewData.Model = model; return(new PageTemplateActionResult(entry.PageTemplate, "Page")); } var comment = entry.Entry.Value.Comment(); comment.AuthorEmail = model.CommenterEmail ?? string.Empty; comment.AuthorName = model.CommenterName ?? string.Empty; comment.AuthorUrl = model.CommenterBlog ?? string.Empty; comment.AuthorIp = Request.UserHostAddress; comment.EntryRevisionNumber = entry.LatestRevisionNumber; comment.Body = model.Comments; try { SpamChecker.Verify(comment); } catch (Exception ex) { HttpContext.Trace.Warn("Akismet is offline, comment cannot be validated: " + ex); } // Anything posted after the disable date is considered spam (the comment box shouldn't be visible anyway) var settings = SettingsProvider.GetSettings <FunnelWebSettings>(); if (settings.DisableCommentsOlderThan > 0 && DateTime.UtcNow.AddDays(settings.DisableCommentsOlderThan) > entry.Published) { comment.IsSpam = true; entry.Entry.Value.CommentCount = entry.Entry.Value.Comments.Count(c => !c.IsSpam); } EventPublisher.Publish(new CommentPostedEvent(entry.Entry.Value, comment)); return(RedirectToAction("Page", new { page }) .AndFlash("Thanks, your comment has been posted.")); }
public ExpandoObject Comment(CommentSaveModel model) { dynamic expandoObject = new ExpandoObject(); var currentMember = Members.GetCurrentMember(); var comment = new Comment { Body = model.Body, MemberId = currentMember.Id, Created = DateTime.Now, ParentCommentId = model.Parent, TopicId = model.Topic }; comment.IsSpam = currentMember.GetPropertyValue <bool>("blocked") || comment.DetectSpam(); CommentService.Save(comment); if (comment.IsSpam) { SpamChecker.SendSlackSpamReport(comment.Body, comment.TopicId, "comment", comment.MemberId); } expandoObject.id = comment.Id; expandoObject.body = comment.Body.Sanitize().ToString(); expandoObject.topicId = comment.TopicId; expandoObject.authorId = comment.MemberId; expandoObject.created = comment.Created.ConvertToRelativeTime(); expandoObject.authorKarma = currentMember.Karma(); expandoObject.authorName = currentMember.Name; expandoObject.roles = currentMember.GetRoles().GetBadges(); expandoObject.cssClass = model.Parent > 0 ? "level-2" : string.Empty; expandoObject.parent = model.Parent; expandoObject.isSpam = comment.IsSpam; SignalRcommentSaved(expandoObject); return(expandoObject); }
public static HtmlString Sanitize(this string html) { // Run it through Markdown first var md = new Markdown(); html = md.Transform(html); // Add links to URLs that aren't "properly" linked in a markdown way var regex = new Regex(@"(^|\s|>|;)(https?|ftp)(:\/\/[-A-Z0-9+&@#\/%?=~_|\[\]\(\)!:,\.;]*[-A-Z0-9+&@#\/%=~_|\[\]])($|\W)", RegexOptions.IgnoreCase | RegexOptions.Compiled); var linkedHtml = regex.Replace(html, "$1<a href=\"$2$3\">$2$3</a>$4").Replace("href=\"www", "href=\"http://www"); var scriptRegex = new Regex("<script.*?</script>", RegexOptions.Singleline | RegexOptions.IgnoreCase); var scriptRegexMatches = scriptRegex.Matches(linkedHtml); for (var i = 0; i < scriptRegexMatches.Count; i++) { linkedHtml = linkedHtml.Replace(scriptRegexMatches[i].Value, $"<pre>{HttpContext.Current.Server.HtmlEncode(scriptRegexMatches[i].Value)}</pre>"); } html = linkedHtml; // Linkify images if they are shown as resized versions (only relevant for new Markdown comments) var doc = new HtmlDocument(); doc.LoadHtml(html); var root = doc.DocumentNode; if (root != null) { var images = root.SelectNodes("//img"); if (images != null) { foreach (var image in images) { var src = image.GetAttributeValue("src", ""); var orgSrc = src.Replace("rs/", ""); if (src == orgSrc || image.ParentNode.Name == "a") { continue; } var a = doc.CreateElement("a"); a.SetAttributeValue("href", orgSrc); a.SetAttributeValue("target", "_blank"); a.AppendChild(image.Clone()); image.ParentNode.ReplaceChild(a, image); } } // Any links not going to an "approved" domain need to be marked as nofollow var links = root.SelectNodes("//a"); if (links != null) { foreach (var link in links) { if (link.Attributes["href"] != null && (SpamChecker.CountValidLinks(link.Attributes["href"].Value, 0) == 0)) { if (link.Attributes["rel"] != null) { link.Attributes.Remove("rel"); } link.Attributes.Add("rel", "nofollow noreferrer noopener"); } } } // Remove styles from all elements var elementsWithStyleAttribute = root.SelectNodes("//@style"); if (elementsWithStyleAttribute != null) { foreach (var element in elementsWithStyleAttribute) { element.Attributes.Remove("style"); } } using (var writer = new StringWriter()) { doc.Save(writer); html = writer.ToString(); } } var sanitizer = new HtmlSanitizer(); var sanitized = sanitizer.Sanitize(html); return(new HtmlString(sanitized)); }
public static HtmlString Sanitize(this string html) { // Run it through Markdown first var md = new Markdown(); html = md.Transform(html); // Linkify images if they are shown as resized versions (only relevant for new Markdown comments) var doc = new HtmlDocument(); doc.LoadHtml(html); var root = doc.DocumentNode; if (root != null) { var images = root.SelectNodes("//img"); if (images != null) { foreach (var image in images) { var src = image.GetAttributeValue("src", ""); var orgSrc = src.Replace("rs/", ""); if (src == orgSrc || image.ParentNode.Name == "a") { continue; } var a = doc.CreateElement("a"); a.SetAttributeValue("href", orgSrc); a.SetAttributeValue("target", "_blank"); a.AppendChild(image.Clone()); image.ParentNode.ReplaceChild(a, image); } } // Any links not going to an "approved" domain need to be marked as nofollow var links = root.SelectNodes("//a"); if (links != null) { foreach (var link in links) { if (link.Attributes["href"] != null && (SpamChecker.CountValidLinks(link.Attributes["href"].Value, 0) == 0)) { if (link.Attributes["rel"] != null) { link.Attributes.Remove("rel"); } link.Attributes.Add("rel", "nofollow"); } } } // Remove styles from all elements var elementsWithStyleAttribute = root.SelectNodes("//@style"); if (elementsWithStyleAttribute != null) { foreach (var element in elementsWithStyleAttribute) { element.Attributes.Remove("style"); } } using (var writer = new StringWriter()) { doc.Save(writer); html = writer.ToString(); } } return(new HtmlString(Utils.Sanitize(html))); }