summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBharat Mediratta <bharat@menalto.com>2009-01-07 07:36:48 +0000
committerBharat Mediratta <bharat@menalto.com>2009-01-07 07:36:48 +0000
commitba052c0cc94a1b1acbe3322e9e3705f71f7134ac (patch)
treea66105cf010350875806e428897c99a31fa47875
parentf8f471c59be38e94242d63ad0facb899594de58d (diff)
Extract the Akismet driver from the Spam_Filter module into a module
in its own right. Clean up the tests, streamline the code and improve the admin interaction. Add a working stats page.
-rw-r--r--modules/akismet/controllers/admin_akismet.php69
-rw-r--r--modules/akismet/helpers/akismet.php142
-rw-r--r--modules/akismet/helpers/akismet_installer.php32
-rw-r--r--modules/akismet/helpers/akismet_menu.php36
-rw-r--r--modules/akismet/module.info3
-rw-r--r--modules/akismet/tests/Akismet_Helper_Test.php90
-rw-r--r--modules/akismet/views/admin_akismet.html.php15
-rw-r--r--modules/akismet/views/admin_akismet_stats.html.php5
-rw-r--r--themes/default/css/screen.css2
9 files changed, 394 insertions, 0 deletions
diff --git a/modules/akismet/controllers/admin_akismet.php b/modules/akismet/controllers/admin_akismet.php
new file mode 100644
index 00000000..6d32868f
--- /dev/null
+++ b/modules/akismet/controllers/admin_akismet.php
@@ -0,0 +1,69 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2008 Bharat Mediratta
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+class Admin_Akismet_Controller extends Admin_Controller {
+ public function index() {
+ $form = akismet::get_configure_form();
+
+ if (request::method() == "post") {
+ $valid = $form->validate();
+
+ if ($valid) {
+ $new_key = $form->configure_akismet->api_key->value;
+ if ($new_key && !akismet::validate_key($new_key)) {
+ $form->configure_akismet->api_key->add_error("invalid", 1);
+ $valid = false;
+ }
+ }
+
+ if ($valid) {
+ $old_key = module::get_var("akismet", "api_key");
+ if ($old_key && !$new_key) {
+ message::success(_("Your Akismet key has been cleared."));
+ } else if ($old_key && $new_key && $old_key != $new_key) {
+ message::success(_("Your Akismet key has been changed."));
+ } else if (!$old_key && $new_key) {
+ message::success(_("Your Akismet key has been saved."));
+ }
+
+ log::success("akismet", _("Akismet key changed to $new_key"));
+ module::set_var("akismet", "api_key", $new_key);
+ url::redirect("admin/akismet");
+ } else {
+ $valid_key = false;
+ }
+ } else {
+ $valid_key = module::get_var("akismet", "api_key") ? 1 : 0;
+ }
+
+ $view = new Admin_View("admin.html");
+ $view->content = new View("admin_akismet.html");
+ $view->content->valid_key = $valid_key;
+ $view->content->form = $form;
+ print $view;
+ }
+
+ public function stats() {
+ $view = new Admin_View("admin.html");
+ $view->content = new View("admin_akismet_stats.html");
+ $view->content->api_key = module::get_var("akismet", "api_key");
+ $view->content->blog_url = url::base(false, "http");
+ print $view;
+ }
+} \ No newline at end of file
diff --git a/modules/akismet/helpers/akismet.php b/modules/akismet/helpers/akismet.php
new file mode 100644
index 00000000..7dbbe98e
--- /dev/null
+++ b/modules/akismet/helpers/akismet.php
@@ -0,0 +1,142 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2008 Bharat Mediratta
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+class akismet_Core {
+ // Lets not send everything to Akismet
+ private static $white_list = array(
+ "HTTP_USER_AGENT",
+ "HTTP_ACCEPT", "HTTP_ACCEPT_CHARSET", "HTTP_ACCEPT_ENCODING",
+ "HTTP_ACCEPT_LANGUAGE", "HTTP_CONNECTION", "HTTP_HOST",
+ "HTTP_KEEP_ALIVE", "HTTP_REFERER", "HTTP_USER_AGENT", "QUERY_STRING",
+ "REMOTE_ADDR", "REMOTE_HOST", "REMOTE_PORT" );
+
+ public static function get_configure_form() {
+ $form = new Forge("admin/akismet", "", "post");
+ $group = $form->group("configure_akismet")->label(_("Configure Akismet"));
+ $group->input("api_key")->label(_("API Key"))->value(module::get_var("akismet", "api_key"));
+ $group->api_key->error_messages("invalid", _("The API key you provided is invalid."));
+ $group->submit(_("Save"));
+ return $form;
+ }
+
+ public static function check_comment($comment) {
+ $request = self::_build_request("comment-check", $comment);
+ $response = self::_http_post($request);
+ return "true" == $response->body[0];
+ }
+
+ public static function submit_spam($comment) {
+ $request = self::_build_request("submit-spam", $comment);
+ $response = self::_http_post($request);
+ return "true" == $response->body[0];
+ }
+
+ public static function submit_ham($comment) {
+ $request = self::_build_request("submit-ham", $comment);
+ $response = self::_http_post($request);
+ return "true" == $response->body[0];
+ }
+
+ public static function validate_key($api_key) {
+ $request = self::_build_verify_request($api_key);
+ $response = self::_http_post($request, "rest.akismet.com");
+ return "valid" == $response->body[0];
+ }
+
+ public static function _build_verify_request($api_key) {
+ $base_url = url::base(false, "http");
+ $query_string = "key={$api_key}&blog=$base_url";
+
+ $version = module::get_version("akismet");
+ $http_request = "POST /1.1/verify-key HTTP/1.0\r\n";
+ $http_request .= "Host: rest.akismet.com\r\n";
+ $http_request .= "Content-Type: application/x-www-form-urlencoded; charset=UTF-8\r\n";
+ $http_request .= "Content-Length: " . strlen($query_string) . "\r\n";
+ $http_request .= "User-Agent: Gallery/3 | Akismet/$version\r\n";
+ $http_request .= "\r\n";
+ $http_request .= $query_string;
+
+ return $http_request;
+ }
+
+ public static function _build_request($function, $comment) {
+ $comment_data = array();
+ $comment_data["user_ip"] = $comment->ip_addr;
+ $comment_data["permalink"] = url::site("comments/{$comment->id}");
+ $comment_data["blog"] = url::base(false, "http");
+ $comment_data["user_agent"] = $comment->user_agent;
+ $comment_data["referrer"] = $_SERVER["HTTP_REFERER"];
+ $comment_data["comment_type"] = "comment";
+ $comment_data["comment_author"] = $comment->author;
+ $comment_data["comment_author_email"] = $comment->email;
+ $comment_data["comment_author_url"] = $comment->url;
+ $comment_data["comment_content"] = $comment->text;
+
+ foreach (self::$white_list as $key) {
+ if (array_key_exists($key, $_SERVER)) {
+ $comment_data[$key] = $_SERVER[$key];
+ }
+ }
+
+ $query_string = array();
+ foreach ($comment_data as $key => $data) {
+ if (!is_array($data)) {
+ $query_string[] = "$key=" . urlencode($data);
+ }
+ }
+ $query_string = join("&", $query_string);
+
+ $version = module::get_version("akismet");
+ $http_request = "POST /1.1/$function HTTP/1.0\r\n";
+ $http_request .= "Host: " . module::get_var("akismet", "api_key") . ".rest.akismet.com\r\n";
+ $http_request .= "Content-Type: application/x-www-form-urlencoded; charset=UTF-8\r\n";
+ $http_request .= "Content-Length: " . strlen($query_string) . "\r\n";
+ $http_request .= "User-Agent: Gallery/3 | Akismet/$version\r\n";
+ $http_request .= "\r\n";
+ $http_request .= $query_string;
+
+ return $http_request;
+ }
+
+ private static function _http_post($http_request, $host=null) {
+ if (!$host) {
+ $host = module::get_var("akismet", "api_key") . ".rest.akismet.com";
+ }
+ $response = "";
+
+ Kohana::log("debug", "Send request\n" . print_r($http_request, 1));
+ if (false !== ($fs = @fsockopen($host, 80, $errno, $errstr, 5))) {
+ fwrite($fs, $http_request);
+ while ( !feof($fs) ) {
+ $response .= fgets($fs, 1160); // One TCP-IP packet
+ }
+ fclose($fs);
+ list($headers, $body) = explode("\r\n\r\n", $response);
+ $headers = explode("\r\n", $headers);
+ $body = explode("\r\n", $body);
+ $response = new ArrayObject(
+ array("headers" => $headers, "body" => $body), ArrayObject::ARRAY_AS_PROPS);
+ } else {
+ throw new Exception("@todo CONNECTION TO SPAM SERVICE FAILED");
+ }
+ Kohana::log("debug", "Received response\n" . print_r($response, 1));
+
+ return $response;
+ }
+}
diff --git a/modules/akismet/helpers/akismet_installer.php b/modules/akismet/helpers/akismet_installer.php
new file mode 100644
index 00000000..cb1bff34
--- /dev/null
+++ b/modules/akismet/helpers/akismet_installer.php
@@ -0,0 +1,32 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2008 Bharat Mediratta
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+class akismet_installer {
+ public static function install() {
+ $version = module::get_version("akismet");
+
+ if ($version == 0) {
+ module::set_version("akismet", 1);
+ }
+ }
+
+ public static function uninstall() {
+ module::delete("akismet");
+ }
+}
diff --git a/modules/akismet/helpers/akismet_menu.php b/modules/akismet/helpers/akismet_menu.php
new file mode 100644
index 00000000..4a0c9b11
--- /dev/null
+++ b/modules/akismet/helpers/akismet_menu.php
@@ -0,0 +1,36 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2008 Bharat Mediratta
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+class akismet_menu_Core {
+ public static function admin($menu, $theme) {
+ $menu->get("settings_menu")
+ ->append(Menu::factory("link")
+ ->id("akismet")
+ ->label(_("Akismet"))
+ ->url(url::site("admin/akismet")));
+
+ if (module::get_var("akismet", "api_key")) {
+ $menu->get("statistics_menu")
+ ->append(Menu::factory("link")
+ ->id("akismet")
+ ->label(_("Akismet"))
+ ->url(url::site("admin/akismet/stats")));
+ }
+ }
+}
diff --git a/modules/akismet/module.info b/modules/akismet/module.info
new file mode 100644
index 00000000..dd2df5dd
--- /dev/null
+++ b/modules/akismet/module.info
@@ -0,0 +1,3 @@
+name = Akismet
+description = "Filter comments through the <a href="http://akismet.com">Akismet web service</a> to detect and eliminate spam. You'll need a <a href="http://wordpress.com/api-keys/">WordPress.com API</a> key to use it."
+version = 1
diff --git a/modules/akismet/tests/Akismet_Helper_Test.php b/modules/akismet/tests/Akismet_Helper_Test.php
new file mode 100644
index 00000000..a508f6c1
--- /dev/null
+++ b/modules/akismet/tests/Akismet_Helper_Test.php
@@ -0,0 +1,90 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2008 Bharat Mediratta
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+class Akismet_Helper_Test extends Unit_Test_Case {
+ private $_comment;
+
+ public function setup() {
+ Input::instance()->ip_address = "1.1.1.1";
+ Kohana::$user_agent = "Akismet_Helper_Test";
+
+ $this->_comment = comment::create(
+ "John Doe", "John@gallery2.org", "This is a comment", 0, "http://gallery2.org");
+ module::set_var("akismet", "api_key", "TEST_KEY");
+ }
+
+ public function build_verify_request_test() {
+ $request = akismet::_build_verify_request("TEST_KEY");
+ $expected =
+ "POST /1.1/verify-key HTTP/1.0\r\n" .
+ "Host: rest.akismet.com\r\n" .
+ "Content-Type: application/x-www-form-urlencoded; charset=UTF-8\r\n" .
+ "Content-Length: 27\r\n" .
+ "User-Agent: Gallery/3 | Akismet/1\r\n\r\n" .
+ "key=TEST_KEY&blog=http://./";
+ $this->assert_equal($expected, $request);
+ }
+
+ public function build_comment_check_request_test() {
+ $request = akismet::_build_request("comment-check", $this->_comment);
+ $expected = "POST /1.1/comment-check HTTP/1.0\r\n" .
+ "Host: TEST_KEY.rest.akismet.com\r\n" .
+ "Content-Type: application/x-www-form-urlencoded; charset=UTF-8\r\n" .
+ "Content-Length: 296\r\n" .
+ "User-Agent: Gallery/3 | Akismet/1\r\n\r\n" .
+ "user_ip=1.1.1.1&permalink=http%3A%2F%2F.%2Findex.php%2Fcomments%2F{$this->_comment->id}" .
+ "&blog=http%3A%2F%2F.%2F&user_agent=Akismet_Helper_Test&referrer=&comment_type=comment" .
+ "&comment_author=John+Doe&comment_author_email=John%40gallery2.org" .
+ "&comment_author_url=http%3A%2F%2Fgallery2.org&comment_content=This+is+a+comment";
+ $this->assert_equal($expected, $request);
+ }
+
+ public function build_submit_spam_request_test() {
+ $request = akismet::_build_request("submit-spam", $this->_comment);
+ $expected =
+ "POST /1.1/submit-spam HTTP/1.0\r\n" .
+ "Host: TEST_KEY.rest.akismet.com\r\n" .
+ "Content-Type: application/x-www-form-urlencoded; charset=UTF-8\r\n" .
+ "Content-Length: 296\r\n" .
+ "User-Agent: Gallery/3 | Akismet/1\r\n\r\n" .
+ "user_ip=1.1.1.1&permalink=http%3A%2F%2F.%2Findex.php%2Fcomments%2F{$this->_comment->id}" .
+ "&blog=http%3A%2F%2F.%2F&user_agent=Akismet_Helper_Test&referrer=&comment_type=comment" .
+ "&comment_author=John+Doe&comment_author_email=John%40gallery2.org" .
+ "&comment_author_url=http%3A%2F%2Fgallery2.org&comment_content=This+is+a+comment";
+
+ $this->assert_equal($expected, $request);
+ }
+
+ public function build_submit_ham_request_test() {
+ $request = akismet::_build_request("submit-ham", $this->_comment);
+ $expected =
+ "POST /1.1/submit-ham HTTP/1.0\r\n" .
+ "Host: TEST_KEY.rest.akismet.com\r\n" .
+ "Content-Type: application/x-www-form-urlencoded; charset=UTF-8\r\n" .
+ "Content-Length: 296\r\n" .
+ "User-Agent: Gallery/3 | Akismet/1\r\n\r\n" .
+ "user_ip=1.1.1.1&permalink=http%3A%2F%2F.%2Findex.php%2Fcomments%2F{$this->_comment->id}" .
+ "&blog=http%3A%2F%2F.%2F&user_agent=Akismet_Helper_Test&referrer=&comment_type=comment" .
+ "&comment_author=John+Doe&comment_author_email=John%40gallery2.org" .
+ "&comment_author_url=http%3A%2F%2Fgallery2.org&comment_content=This+is+a+comment";
+
+ $this->assert_equal($expected, $request);
+ }
+}
+
diff --git a/modules/akismet/views/admin_akismet.html.php b/modules/akismet/views/admin_akismet.html.php
new file mode 100644
index 00000000..34a5461b
--- /dev/null
+++ b/modules/akismet/views/admin_akismet.html.php
@@ -0,0 +1,15 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<div id="gAdminAkismet">
+ <h1> <?= _("Akismet Spam Filtering") ?> </h1>
+ <p>
+ <?= _("Akismet is a free, automated spam filtering service. In order to use it, you need to sign up for a <a href=\"http://wordpress.com/api-keys\">Wordpress.com API Key</a>, which is also free. Your comments will be automatically relayed to <a href=\"http://akismet.com\">Akismet.com</a> where they'll be scanned for spam. Spam messages will be flagged accordingly and hidden from your vistors until you approve or delete them.") ?>
+ </p>
+
+ <? if ($valid_key): ?>
+ <div class="gSuccess">
+ <?= _("Your API Key is valid. Your comments will be filtered!") ?>
+ </div>
+ <? endif ?>
+
+ <?= $form ?>
+</div>
diff --git a/modules/akismet/views/admin_akismet_stats.html.php b/modules/akismet/views/admin_akismet_stats.html.php
new file mode 100644
index 00000000..a36ef237
--- /dev/null
+++ b/modules/akismet/views/admin_akismet_stats.html.php
@@ -0,0 +1,5 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<iframe width="100%"
+ style="border: 0px"
+ src="http://<?= $api_key ?>.web.akismet.com/1.0/user-stats.php?blog=<?= urlencode($blog_url) ?>">
+</iframe>
diff --git a/themes/default/css/screen.css b/themes/default/css/screen.css
index e990571a..9a955699 100644
--- a/themes/default/css/screen.css
+++ b/themes/default/css/screen.css
@@ -266,6 +266,7 @@ li.gError select {
/* Status messages ~~~~~~~~~~~~~~~~~~~~~~~ */
+#gAdminAkismet .gSuccess,
#gSiteStatus li,
#gMessage li {
border: 1px solid #ccc;
@@ -299,6 +300,7 @@ li.gError select {
background-image: url('../images/ico-info.png');
}
+#gAdminAkismet .gSuccess,
#gSiteStatus .gSuccess,
#gMessage .gSuccess {
background-color: #cfc;