using System; using System.Net; using System.Web; using System.IO; using BlogEngine.Core; using BlogEngine.Core.Web.Controls; using Joel.Net; /// /// Summary description for AkismetFilter /// [Extension("Akismet anti-spam comment filter", "1.0", "BlogEngine.NET")] public class AkismetFilter : ICustomFilter { #region Private members private static ExtensionSettings _settings; private static Akismet _api; private static string _site; private static string _key; #endregion public AkismetFilter() { InitSettings(); } #region ICustomFilter implementation public bool Initialize() { if (!ExtensionManager.ExtensionEnabled("AkismetFilter")) return false; if (_settings == null) InitSettings(); _site = _settings.GetSingleValue("SiteURL"); _key = _settings.GetSingleValue("ApiKey"); _api = new Akismet(_key, _site, "BlogEngine.net 1.6"); return _api.VerifyKey(); } public bool Check(Comment comment) { if (_api == null) Initialize(); if (_settings == null) InitSettings(); AkismetComment akismetComment = GetAkismetComment(comment); return _api.CommentCheck(akismetComment); } public void Report(Comment comment) { if (_api == null) Initialize(); if (_settings == null) InitSettings(); AkismetComment akismetComment = GetAkismetComment(comment); if (comment.IsApproved) { Utils.Log(string.Format("Akismet: Reporting NOT spam from \"{0}\" at \"{1}\"", comment.Author, comment.IP)); _api.SubmitHam(akismetComment); } else { Utils.Log(string.Format("Akismet: Reporting SPAM from \"{0}\" at \"{1}\"", comment.Author, comment.IP)); _api.SubmitSpam(akismetComment); } } public bool FallThrough { get { return true; } } #endregion #region Private methods private AkismetComment GetAkismetComment(Comment comment) { AkismetComment akismetComment = new AkismetComment(); akismetComment.Blog = _settings.GetSingleValue("SiteURL"); akismetComment.UserIp = comment.IP; akismetComment.CommentContent = comment.Content; akismetComment.CommentType = "comment"; akismetComment.CommentAuthor = comment.Author; akismetComment.CommentAuthorEmail = comment.Email; if (comment.Website != null) { akismetComment.CommentAuthorUrl = comment.Website.OriginalString; } return akismetComment; } private void InitSettings() { ExtensionSettings settings = new ExtensionSettings(this); settings.IsScalar = true; settings.AddParameter("SiteURL", "Site URL"); settings.AddParameter("ApiKey", "API Key"); settings.AddValue("SiteURL", "http://example.com/blog"); settings.AddValue("ApiKey", "123456789"); _settings = ExtensionManager.InitSettings("AkismetFilter", settings); ExtensionManager.SetStatus("AkismetFilter", false); } #endregion } /* Author: Joel Thoms (http://joel.net) * Copyright: 2006 Joel Thoms (http://joel.net) * About: Akismet (http://akismet.com) .Net 2.0 API allow you to check * Akismet's spam database to verify your comments and prevent spam. * * Note: Do not launch 'DEBUG' code on your site. Only build 'RELEASE' for your site. Debug code contains * Console.WriteLine's, which are not desireable on a website. */ namespace Joel.Net { #region - public class AkismetComment - public class AkismetComment { public string Blog = null; public string UserIp = null; public string UserAgent = null; public string Referrer = null; public string Permalink = null; public string CommentType = null; public string CommentAuthor = null; public string CommentAuthorEmail = null; public string CommentAuthorUrl = null; public string CommentContent = null; } #endregion public class Akismet { const string verifyUrl = "http://rest.akismet.com/1.1/verify-key"; const string commentCheckUrl = "http://{0}.rest.akismet.com/1.1/comment-check"; const string submitSpamUrl = "http://{0}.rest.akismet.com/1.1/submit-spam"; const string submitHamUrl = "http://{0}.rest.akismet.com/1.1/submit-ham"; string apiKey = null; string userAgent = "Joel.Net's Akismet API/1.0"; string blog = null; public string CharSet = "UTF-8"; /// Creates an Akismet API object. /// Your wordpress.com API key. /// URL to your blog /// Name of application using API. example: "Joel.Net's Akismet API/1.0" /// Accepts required fields 'apiKey', 'blog', 'userAgent'. public Akismet(string apiKey, string blog, string userAgent) { this.apiKey = apiKey; if (userAgent != null) this.userAgent = userAgent + " | Akismet/1.11"; this.blog = blog; } /// Verifies your wordpress.com key. /// 'True' is key is valid. public bool VerifyKey() { bool value = false; string response = HttpPost(verifyUrl, String.Format("key={0}&blog={1}", apiKey, HttpUtility.UrlEncode(blog)), CharSet); value = (response == "valid") ? true : false; return value; } /// Checks AkismetComment object against Akismet database. /// AkismetComment object to check. /// 'True' if spam, 'False' if not spam. public bool CommentCheck(AkismetComment comment) { bool value = false; value = Convert.ToBoolean(HttpPost(String.Format(commentCheckUrl, apiKey), CreateData(comment), CharSet)); return value; } /// Submits AkismetComment object into Akismet database. /// AkismetComment object to submit. public void SubmitSpam(AkismetComment comment) { string value = HttpPost(String.Format(submitSpamUrl, apiKey), CreateData(comment), CharSet); } /// Retracts false positive from Akismet database. /// AkismetComment object to retract. public void SubmitHam(AkismetComment comment) { string value = HttpPost(String.Format(submitHamUrl, apiKey), CreateData(comment), CharSet); } #region - Private Methods (CreateData, HttpPost) - /// Takes an AkismetComment object and returns an (escaped) string of data to POST. /// AkismetComment object to translate. /// A System.String containing the data to POST to Akismet API. private string CreateData(AkismetComment comment) { string value = String.Format("blog={0}&user_ip={1}&user_agent={2}&referrer={3}&permalink={4}&comment_type={5}" + "&comment_author={6}&comment_author_email={7}&comment_author_url={8}&comment_content={9}", HttpUtility.UrlEncode(comment.Blog), HttpUtility.UrlEncode(comment.UserIp), HttpUtility.UrlEncode(comment.UserAgent), HttpUtility.UrlEncode(comment.Referrer), HttpUtility.UrlEncode(comment.Permalink), HttpUtility.UrlEncode(comment.CommentType), HttpUtility.UrlEncode(comment.CommentAuthor), HttpUtility.UrlEncode(comment.CommentAuthorEmail), HttpUtility.UrlEncode(comment.CommentAuthorUrl), HttpUtility.UrlEncode(comment.CommentContent) ); return value; } /// Sends HttpPost /// URL to Post data to. /// Data to post. example: key=<wordpress-key>&blog=http://joel.net /// Character set of your blog. example: UTF-8 /// A System.String containing the Http Response. private string HttpPost(string url, string data, string charSet) { string value = ""; // Initialize Connection HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.Method = "POST"; request.ContentType = "application/x-www-form-urlencoded; charset=" + charSet; request.UserAgent = userAgent; request.ContentLength = data.Length; // Write Data StreamWriter writer = new StreamWriter(request.GetRequestStream()); writer.Write(data); writer.Close(); // Read Response HttpWebResponse response = (HttpWebResponse)request.GetResponse(); StreamReader reader = new StreamReader(response.GetResponseStream()); value = reader.ReadToEnd(); reader.Close(); return value; } #endregion } }