summaryrefslogtreecommitdiff
path: root/modules/recaptcha
diff options
context:
space:
mode:
authorTim Almdal <tnalmdal@shaw.ca>2009-01-23 17:05:20 +0000
committerTim Almdal <tnalmdal@shaw.ca>2009-01-23 17:05:20 +0000
commit3438bf7b3dd3a89f0104b6964008b699b769324e (patch)
tree81f950221eecada334c34c1b97d81681b4073cd0 /modules/recaptcha
parentf75a803cd67283c24cc54a001163f9ee47210010 (diff)
The adminstration portion of the recaptcha module. I haven't figured out how to integrate it with the other module forms.
Diffstat (limited to 'modules/recaptcha')
-rw-r--r--modules/recaptcha/controllers/admin_recaptcha.php105
-rw-r--r--modules/recaptcha/helpers/recaptcha.php177
-rw-r--r--modules/recaptcha/helpers/recaptcha_installer.php35
-rw-r--r--modules/recaptcha/helpers/recaptcha_menu.php28
-rw-r--r--modules/recaptcha/module.info3
-rw-r--r--modules/recaptcha/views/admin_recaptcha.html.php53
6 files changed, 401 insertions, 0 deletions
diff --git a/modules/recaptcha/controllers/admin_recaptcha.php b/modules/recaptcha/controllers/admin_recaptcha.php
new file mode 100644
index 00000000..0f05a82b
--- /dev/null
+++ b/modules/recaptcha/controllers/admin_recaptcha.php
@@ -0,0 +1,105 @@
+<?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_Recaptcha_Controller extends Admin_Controller {
+ public function index() {
+ $form = recaptcha::get_configure_form();
+ $old_public_key = module::get_var("recaptcha", "public_key");
+ $old_private_key = module::get_var("recaptcha", "private_key");
+ if (request::method() == "post") {
+
+ $valid_key = $form->validate();
+ if ($valid_key) {
+ $valid_key = recaptcha::is_recaptcha_valid($form,
+ $form->configure_recaptcha->private_key->value);
+ if (empty($valid_key) && $form->captcha_error == "invalid-site-private-key") {
+ $form->configure_recaptcha->private_key->add_error("invalid", 1);
+ unset($form->captcha_error);
+ }
+ }
+ if ($valid_key) {
+ $new_public_key = $form->configure_recaptcha->public_key->value;
+ $new_private_key = $form->configure_recaptcha->private_key->value;
+
+ $updated = false;
+ if ($this->_update_key("public_key", $old_public_key, $new_public_key) ||
+ $this->_update_key("private_key", $old_private_key, $new_private_key)) {
+ message::success(t("Recaptcha Configured"));
+ }
+ recaptcha::check_config();
+ }
+ } else {
+ $valid_key = !empty($old_public_key) && !empty($old_private_key);
+ }
+
+ recaptcha::check_config();
+ $view = new Admin_View("admin.html");
+ $view->content = new View("admin_recaptcha.html");
+ $view->content->valid_key = $valid_key;
+ $view->content->form = $form;
+ print $view;
+ }
+
+ private function _update_key($type, $old_key, $new_key) {
+ $changed = true;
+ if ($old_key && !$new_key) {
+ log::success(sprintf(t("Your Recaptcha %s has been cleared."), strtr($type, "_", " ")));
+ } else if ($old_key && $new_key && $old_key != $new_key) {
+ log::success(sprintf(t("Your Recaptcha %s has been changed."), strtr($type, "_", " ")));
+ } else if (!$old_key && $new_key) {
+ log::success(sprintf(t("Your Recaptcha %s has been saved."), strtr($type, "_", " ")));
+ } else {
+ $changed = false;
+ }
+ if ($changed) {
+ module::set_var("recaptcha", $key, $new_key);
+ }
+
+ }
+
+ public function gethtml($public_key, $error=null) {
+ $http_request = "GET /challenge?k=$public_key HTTP/1.0\r\n";
+ $response = "";
+ if( false == ( $fs = @fsockopen("api.recaptcha.net", 80, $errno, $errstr, 10) ) ) {
+ throw new Exception("@todo COULD NOT OPEN SOCKET");
+ }
+ $errorpart = empty($error) ? "" : "&error=$error";
+ fputs($fs, "GET /challenge?k=$public_key&ajax=1$errorpart HTTP/1.0\r\n");
+ fputs($fs, "Host: api.recaptcha.net\r\n");
+ fputs($fs, "Connection: Close\r\n\r\n");
+ while (!feof($fs)) {
+ $response .= fgets($fs, 1160); // One TCP-IP packet
+ }
+ fclose($fs);
+ $response = explode("\r\n\r\n", $response, 2);
+
+ if (strpos($response[1], "document.write") === 0) {
+ header("HTTP/1.1 400 BAD REQUEST");
+ if (preg_match("#.*\'(.*)\'#", $response[1], $matches)) {
+ $msg = $matches[1];
+ } else {
+ $msg = _t("Unable to determine error message");
+ }
+ print $msg;
+ } else {
+ header("HTTP/1.1 200 OK");
+ print json_encode(array("result" => "success", "script" => $response[1]));
+ }
+ }
+}
diff --git a/modules/recaptcha/helpers/recaptcha.php b/modules/recaptcha/helpers/recaptcha.php
new file mode 100644
index 00000000..69361e23
--- /dev/null
+++ b/modules/recaptcha/helpers/recaptcha.php
@@ -0,0 +1,177 @@
+<?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 recaptcha_Core {
+ /**
+ * The reCAPTCHA server URL"s
+ */
+ const API_SERVER = "http://api.recaptcha.net";
+ const API_SECURE_SERVER = "https://api-secure.recaptcha.net";
+ const VERIFY_SERVER = "api-verify.recaptcha.net";
+
+ /**
+ * RecaptchaOptions
+ */
+ private $options = array();
+
+ static function get_configure_form() {
+ $form = new Forge("admin/recaptcha", "", "post");
+ $group = $form->group("configure_recaptcha")
+ ->label(t("Configure Recaptcha"));
+ $group->hidden("orig_public_key")
+ ->value(module::get_var());
+ $group->input("public_key")
+ ->label(t("Public Key"))
+ ->value(module::get_var("recaptcha", "public_key"))
+ ->rules("required|length[40]");
+ $group->public_key->error_messages("invalid", t("The public key you provided is invalid."));
+ $group->input("private_key")
+ ->label(t("Private Key"))
+ ->value(module::get_var("recaptcha", "private_key"))
+ ->rules("required|length[40]");
+ $group->private_key->error_messages("invalid", t("The private key you provided is invalid."));
+ $group->submit("")->value(t("Save"));
+ $site_domain = urlencode(stripslashes($_SERVER["HTTP_HOST"]));
+ $form->recaptcha_site = self::API_SERVER;
+ $form->recaptcha_ssl_site = self::API_SECURE_SERVER;
+ $form->get_key_url = "http://recaptcha.net/api/getkey?domain=$site_domain&app=Gallery3";
+ return $form;
+ }
+
+ static function check_config() {
+ $public_key = module::get_var("recaptcha", "public_key");
+ $private_key = module::get_var("recaptcha", "private_key");
+ if (empty($public_key) || empty($private_key)) {
+ site_status::warning(
+ t("Recaptcha is not quite ready! Please configure the <a href=\"%url\">Recaptcha Keys</a>",
+ array("url" => url::site("admin/recaptcha"))),
+ "recaptcha_config");
+ } else {
+ site_status::clear("recaptcha_config");
+ }
+ }
+
+ /**
+ * Gets the challenge HTML (javascript and non-javascript version).
+ * This is called from the browser, and the resulting reCAPTCHA HTML widget
+ * is embedded within the HTML form it was called from.
+ * @param string $pubkey The public key to use in the challenge
+ * @param string $error The error given by reCAPTCHA (optional, default is null)
+ * @param boolean $use_ssl Should the request be made over ssl? (optional, default is false)
+ * @param string $lang Any supported language code
+ * @return string - The HTML to be embedded in the user"s form.
+ */
+ static function get_challenge_html($pubkey, $error = NULL, $use_ssl = false) {
+ if (empty($pubkey)) {
+ throw new Exception("@todo NEED KEY <a href=\"http://recaptcha.net/api/getkey\">" .
+ "http://recaptcha.net/api/getkey</a>");
+ }
+
+ $lang = Kohana::config("locale.root_locale");
+ $server = $use_ssl ? self::API_SECURE_SERVER : self::API_SERVER;
+ $errorpart = "";
+ if ($error) {
+ $errorpart = "&amp;error=". $error;
+ }
+ return (count(self::$options) > 0 ? "<script type=\"text/javascript\">" .
+ "var RecaptchaOptions = {lang:'$lang'};</script>" : "") .
+ "<script type=\"text/javascript\" src=\"$server/challenge?k=" .
+ "{$pubkey}$errorpart \"></script>" . $noscript;
+ }
+
+ /**
+ * Form validation call back for captcha validation
+ * @param string $form
+ * @return true if valid, false if not
+ */
+ static function is_recaptcha_valid($form, $private_key=null) {
+ $input = Input::instance();
+
+ if (empty($private_key)) {
+ $private_key = module::get_var("recaptcha", "private_key");
+ }
+ Kohana::log("debug", $private_key);
+ $remoteip = $_SERVER["REMOTE_ADDR"] ;
+ $challenge = $input->post("recaptcha_challenge_field", "", true);
+ $response = $input->post("recaptcha_response_field", "", true);
+
+ //discard spam submissions
+ if (empty($challenge) || empty($response)) {
+ $form->captcha_error = "incorrect-captcha-sol";
+ return false;
+ }
+ $response = self::_http_post(self::VERIFY_SERVER, "/verify",
+ array ("privatekey" => $private_key,
+ "remoteip" => $remoteip,
+ "challenge" => $challenge,
+ "response" => $response));
+
+ $answers = explode ("\n", $response [1]);
+ if (trim ($answers [0]) == "true") {
+ return true;
+ } else {
+ $form->captcha_error = $answers[1];
+ Kohana::log("debug", print_r($answers, 1));
+ return false;
+ }
+ }
+
+ /**
+ * Encodes the given data into a query string format
+ * @param $data - array of string elements to be encoded
+ * @return string - encoded request
+ */
+ private static function _encode(array $data){
+ $req = array();
+ foreach ($data as $key => $value){
+ $req[] = "$key=" . urlencode(stripslashes($value));
+ }
+ return implode("&", $req);
+ }
+
+ /**
+ * Submits an HTTP POST to a reCAPTCHA server
+ * @param string $host
+ * @param string $path
+ * @param array $data
+ * @param int port
+ * @return array response
+ */
+ private static function _http_post($host, $path, $data, $port = 80) {
+ $req = self::_encode($data);
+ $http_request = "POST $path HTTP/1.0\r\n";
+ $http_request .= "Host: $host\r\n";
+ $http_request .= "Content-Type: application/x-www-form-urlencoded;\r\n";
+ $http_request .= "Content-Length: " . strlen($req) . "\r\n";
+ $http_request .= "User-Agent: reCAPTCHA/PHP\r\n";
+ $http_request .= "\r\n";
+ $http_request .= $req;
+ $response = "";
+ if( false == ( $fs = @fsockopen($host, $port, $errno, $errstr, 10) ) ) {
+ throw new Exception("@todo COULD NOT OPEN SOCKET");
+ }
+ fwrite($fs, $http_request);
+ while (!feof($fs)) {
+ $response .= fgets($fs, 1160); // One TCP-IP packet
+ }
+ fclose($fs);
+ $response = explode("\r\n\r\n", $response, 2);
+ return $response;
+ }
+}
diff --git a/modules/recaptcha/helpers/recaptcha_installer.php b/modules/recaptcha/helpers/recaptcha_installer.php
new file mode 100644
index 00000000..f4f63739
--- /dev/null
+++ b/modules/recaptcha/helpers/recaptcha_installer.php
@@ -0,0 +1,35 @@
+<?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 recaptcha_installer {
+ static function install() {
+ $version = module::get_version("recaptcha");
+
+ if ($version == 0) {
+ module::set_version("recaptcha", 1);
+ }
+
+ recaptcha::check_config();
+ }
+
+ static function uninstall() {
+ site_status::clear("recaptcha_config");
+ module::delete("recaptcha");
+ }
+}
diff --git a/modules/recaptcha/helpers/recaptcha_menu.php b/modules/recaptcha/helpers/recaptcha_menu.php
new file mode 100644
index 00000000..59cb9d84
--- /dev/null
+++ b/modules/recaptcha/helpers/recaptcha_menu.php
@@ -0,0 +1,28 @@
+<?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 recaptcha_menu_Core {
+ static function admin($menu, $theme) {
+ $menu->get("settings_menu")
+ ->append(Menu::factory("link")
+ ->id("recaptcha")
+ ->label(t("Recaptcha"))
+ ->url(url::site("admin/recaptcha")));
+ }
+}
diff --git a/modules/recaptcha/module.info b/modules/recaptcha/module.info
new file mode 100644
index 00000000..134ae31c
--- /dev/null
+++ b/modules/recaptcha/module.info
@@ -0,0 +1,3 @@
+name = Recaptcha
+description = "<a href="http://recaptcha.net">Recaptcha</a> displays a graphical verification that protects the input form from abuse from "bots," or automated programs usually written to generate spam."
+version = 1
diff --git a/modules/recaptcha/views/admin_recaptcha.html.php b/modules/recaptcha/views/admin_recaptcha.html.php
new file mode 100644
index 00000000..ebba31d5
--- /dev/null
+++ b/modules/recaptcha/views/admin_recaptcha.html.php
@@ -0,0 +1,53 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<script type="text/javascript" src="http://api.recaptcha.net/js/recaptcha_ajax.js"></script>
+<script>
+var site = (document.location.protocol == "http:") ? "<?= $form->recaptcha_site ?>" : "<?= $form->recaptcha_ssl_site ?>";
+var RecaptchaOptions = {lang: 'en'};
+
+$("#gAdminRecaptcha form").ready(function() {
+ $("#gAdminRecaptcha form ul li:last-child").before("<li id=recaptcha_div />");
+ $("#public_key").change(function() {
+ showRecaptcha($(this).val());
+ });
+ var original = $("#public_key").val();
+ if (original != "") {
+ showRecaptcha(original);
+ }
+});
+
+function showRecaptcha(public_key) {
+ if (public_key != "") {
+ Recaptcha.widget = document.getElementById("recaptcha_div");
+ $.ajax({url: "<?= url::site("admin/recaptcha/gethtml") ?>/" + public_key <? if (!empty($form->captcha_error)): ?> + "/<?= $form->captcha_error ?>" <? endif ?> ,
+ dataType: "json",
+ cache: false,
+ error: function(request, textStatus, errorThrown) {
+ var public_key = $("#gAdminRecaptcha form ul li:first-child");
+ public_key.addClass("gError");
+ $("#gAdminRecaptcha form ul li:first-child p").replaceWith("");
+ public_key.append('<p class="gError">' + request.responseText + "</p>");
+ },
+ success: function(data, textStatus) {
+ var public_key = $("#gAdminRecaptcha form ul li:first-child");
+ public_key.removeClass("gError");
+ $("#gAdminRecaptcha form ul li:first-child p").replaceWith("");
+ $("#recaptcha_div").html("<script type='text/javascript'>" + data.script + "</script" + ">");
+ }
+ });
+ } else {
+ if (Recaptcha.widget != undefined) {
+ Recaptcha.destroy();
+ }
+ }
+}
+
+</script>
+
+<div id="gAdminRecaptcha">
+ <h1> <?= t("ReCaptcha Challenge Filtering") ?> </h1>
+ <p>
+ <?= t("Recaptcha is a free CAPTCHA service that helps to digitize books, newspapers and old time radio shows. automated spam filtering service. In order to use it, you need to sign up for a <a href=\"{$form->get_key_url}\">ReCaptcha Public/Private Key pair</a>, which is also free. Once registered, the the challenge and response strings are evaluated at <a href=\"http://recaptcha.net\">recaptcha.net</a> to determine if the form content has been entered by a bot.") ?>
+ </p>
+
+ <?= $form ?>
+</div>