<?php␊ |
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */␊ |
/*␊ |
# ***** BEGIN LICENSE BLOCK *****␊ |
# This file is part of Plume Framework, a simple PHP Application Framework.␊ |
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.␊ |
#␊ |
# Plume Framework is free software; you can redistribute it and/or modify␊ |
# it under the terms of the GNU Lesser General Public License as published by␊ |
# the Free Software Foundation; either version 2.1 of the License, or␊ |
# (at your option) any later version.␊ |
#␊ |
# Plume Framework 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 Lesser General Public License for more details.␊ |
#␊ |
# You should have received a copy of the GNU Lesser General Public License␊ |
# along with this program; if not, write to the Free Software␊ |
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA␊ |
#␊ |
# ***** END LICENSE BLOCK ***** */␊ |
␊ |
/**␊ |
* Add ReCaptcha control to your forms.␊ |
*␊ |
* You need first to get a ReCaptcha account, create a domain and get␊ |
* the API keys for your domain. Check http://recaptcha.net/ for more␊ |
* information.␊ |
*␊ |
* The recaptcha field needs to know the IP address of the user␊ |
* submitting the form and if the request is made over SSL or␊ |
* not. This means that you need to provide the $request object in the␊ |
* extra parameters of your form.␊ |
*␊ |
* To add the ReCaptcha field to your form, simply add the following␊ |
* to your form object (note the use of $extra['request']):␊ |
*␊ |
* <pre>␊ |
* $ssl = (!empty($extra['request']->SERVER['HTTPS']) ␊ |
* and $extra['request']->SERVER['HTTPS'] != 'off');␊ |
*␊ |
* $this->fields['recaptcha'] = new Pluf_Form_Field_ReCaptcha(␊ |
* array('required' => true,␊ |
* 'label' => __('Please solve this challenge'),␊ |
* 'privkey' => 'PRIVATE_RECAPTCHA_KEY_HERE',␊ |
* 'remoteip' => $extra['request']->remote_addr,␊ |
* 'widget_attrs' => array(␊ |
* 'pubkey' => 'PUBLIC_RECAPTCHA_KEY_HERE',␊ |
* ),␊ |
* ));␊ |
* </pre>␊ |
*␊ |
* Then in your template, you simply need to add the ReCaptcha field:␊ |
* ␊ |
* <pre>␊ |
* {if $form.f.recaptcha.errors}{$form.f.recaptcha.fieldErrors}{/if}␊ |
* {$form.f.recaptcha|safe}␊ |
* </pre>␊ |
*␊ |
* Based on http://recaptcha.googlecode.com/files/recaptcha-php-1.10.zip␊ |
*␊ |
* Copyright (c) 2007 reCAPTCHA -- http://recaptcha.net␊ |
* AUTHORS:␊ |
* Mike Crawford␊ |
* Ben Maurer␊ |
*/␊ |
class Pluf_Form_Field_ReCaptcha extends Pluf_Form_Field␊ |
{␊ |
public $widget = 'Pluf_Form_Widget_ReCaptcha';␊ |
public $privkey = '';␊ |
public $remoteip = '';␊ |
public $extra_params = array();␊ |
␊ |
public function clean($value)␊ |
{␊ |
// will throw the Pluf_Form_Invalid exception in case of␊ |
// error.␊ |
self::checkAnswer($this->privkey, $this->remoteip, ␊ |
$value[0], $value[1], $this->extra_params);␊ |
return $value;␊ |
}␊ |
␊ |
/**␊ |
* Submits an HTTP POST to a reCAPTCHA server␊ |
*␊ |
* @param string Host␊ |
* @param string Path␊ |
* @param array Data␊ |
* @param int port (80␊ |
* @return array response␊ |
*/␊ |
public static function httpPost($host, $path, $data, $port=80) ␊ |
{␊ |
␊ |
$req = self::qsencode($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;␊ |
␊ |
if (false === ($fs=@fsockopen($host, $port, $errno, $errstr, 10))) {␊ |
throw new Pluf_Form_Invalid(__('Cannot connect to the reCaptcha server for validation.'));␊ |
}␊ |
fwrite($fs, $http_request);␊ |
$response = '';␊ |
while (!feof($fs)) {␊ |
$response .= fgets($fs, 1160); // One TCP-IP packet␊ |
}␊ |
fclose($fs);␊ |
return explode("\r\n\r\n", $response, 2);␊ |
}␊ |
␊ |
/**␊ |
* Encodes the given data into a query string format␊ |
*␊ |
* @param array Array of string elements to be encoded␊ |
* @return string Encoded request␊ |
*/␊ |
public static function qsencode($data) ␊ |
{␊ |
$d = array();␊ |
foreach ($data as $key => $value) {␊ |
$d[] = $key.'='.urlencode(stripslashes($value));␊ |
}␊ |
return implode('&', $d);␊ |
}␊ |
␊ |
/**␊ |
* Calls an HTTP POST function to verify if the user's guess was correct␊ |
* @param string $privkey␊ |
* @param string $remoteip␊ |
* @param string $challenge␊ |
* @param string $response␊ |
* @param array $extra_params an array of extra variables to post to the server␊ |
* @return ReCaptchaResponse␊ |
*/␊ |
public static function checkAnswer($privkey, $remoteip, $challenge, $response, $extra_params=array())␊ |
{␊ |
if ($privkey == '') {␊ |
throw new Pluf_Form_Invalid(__('To use reCAPTCHA you must set your API key.'));␊ |
}␊ |
if ($remoteip == '') {␊ |
throw new Pluf_Form_Invalid(__('For security reasons, you must pass the remote ip to reCAPTCHA.'));␊ |
}␊ |
//discard spam submissions␊ |
if (strlen($challenge) == 0 || strlen($response) == 0) {␊ |
return false;␊ |
}␊ |
␊ |
$response = self::httpPost('api-verify.recaptcha.net', '/verify',␊ |
array(␊ |
'privatekey' => $privkey,␊ |
'remoteip' => $remoteip,␊ |
'challenge' => $challenge,␊ |
'response' => $response␊ |
) + $extra_params␊ |
);␊ |
␊ |
$answers = explode("\n", $response[1]);␊ |
if (trim($answers[0]) == 'true') {␊ |
return true;␊ |
} else {␊ |
throw new Pluf_Form_Invalid($answers[1]);␊ |
}␊ |
}␊ |
}␊ |