507 lines
12 KiB
PHP
507 lines
12 KiB
PHP
|
<?php
|
||
|
/**
|
||
|
* Zend Framework
|
||
|
*
|
||
|
* LICENSE
|
||
|
*
|
||
|
* This source file is subject to the new BSD license that is bundled
|
||
|
* with this package in the file LICENSE.txt.
|
||
|
* It is also available through the world-wide-web at this URL:
|
||
|
* http://framework.zend.com/license/new-bsd
|
||
|
* If you did not receive a copy of the license and are unable to
|
||
|
* obtain it through the world-wide-web, please send an email
|
||
|
* to license@zend.com so we can send you a copy immediately.
|
||
|
*
|
||
|
* @category Zend
|
||
|
* @package Zend_Service
|
||
|
* @subpackage ReCaptcha
|
||
|
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
|
||
|
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||
|
*/
|
||
|
|
||
|
/** @see Zend_Service_Abstract */
|
||
|
require_once 'Zend/Service/Abstract.php';
|
||
|
|
||
|
/** @see Zend_Json */
|
||
|
require_once 'Zend/Json.php';
|
||
|
|
||
|
/** @see Zend_Service_ReCaptcha_Response */
|
||
|
require_once 'Zend/Service/ReCaptcha/Response.php';
|
||
|
|
||
|
/**
|
||
|
* Zend_Service_ReCaptcha
|
||
|
*
|
||
|
* @category Zend
|
||
|
* @package Zend_Service
|
||
|
* @subpackage ReCaptcha
|
||
|
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
|
||
|
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||
|
* @version $Id: ReCaptcha.php 16971 2009-07-22 18:05:45Z mikaelkael $
|
||
|
*/
|
||
|
class Zend_Service_ReCaptcha extends Zend_Service_Abstract
|
||
|
{
|
||
|
/**
|
||
|
* URI to the regular API
|
||
|
*
|
||
|
* @var string
|
||
|
*/
|
||
|
const API_SERVER = 'http://api.recaptcha.net';
|
||
|
|
||
|
/**
|
||
|
* URI to the secure API
|
||
|
*
|
||
|
* @var string
|
||
|
*/
|
||
|
const API_SECURE_SERVER = 'https://api-secure.recaptcha.net';
|
||
|
|
||
|
/**
|
||
|
* URI to the verify server
|
||
|
*
|
||
|
* @var string
|
||
|
*/
|
||
|
const VERIFY_SERVER = 'http://api-verify.recaptcha.net/verify';
|
||
|
|
||
|
/**
|
||
|
* Public key used when displaying the captcha
|
||
|
*
|
||
|
* @var string
|
||
|
*/
|
||
|
protected $_publicKey = null;
|
||
|
|
||
|
/**
|
||
|
* Private key used when verifying user input
|
||
|
*
|
||
|
* @var string
|
||
|
*/
|
||
|
protected $_privateKey = null;
|
||
|
|
||
|
/**
|
||
|
* Ip address used when verifying user input
|
||
|
*
|
||
|
* @var string
|
||
|
*/
|
||
|
protected $_ip = null;
|
||
|
|
||
|
/**
|
||
|
* Parameters for the object
|
||
|
*
|
||
|
* @var array
|
||
|
*/
|
||
|
protected $_params = array(
|
||
|
'ssl' => false, /* Use SSL or not when generating the recaptcha */
|
||
|
'error' => null, /* The error message to display in the recaptcha */
|
||
|
'xhtml' => false /* Enable XHTML output (this will not be XHTML Strict
|
||
|
compliant since the IFRAME is necessary when
|
||
|
Javascript is disabled) */
|
||
|
);
|
||
|
|
||
|
/**
|
||
|
* Options for tailoring reCaptcha
|
||
|
*
|
||
|
* See the different options on http://recaptcha.net/apidocs/captcha/client.html
|
||
|
*
|
||
|
* @var array
|
||
|
*/
|
||
|
protected $_options = array(
|
||
|
'theme' => 'red',
|
||
|
'lang' => 'en',
|
||
|
);
|
||
|
|
||
|
/**
|
||
|
* Response from the verify server
|
||
|
*
|
||
|
* @var Zend_Service_ReCaptcha_Response
|
||
|
*/
|
||
|
protected $_response = null;
|
||
|
|
||
|
/**
|
||
|
* Class constructor
|
||
|
*
|
||
|
* @param string $publicKey
|
||
|
* @param string $privateKey
|
||
|
* @param array $params
|
||
|
* @param array $options
|
||
|
* @param string $ip
|
||
|
* @param array|Zend_Config $params
|
||
|
*/
|
||
|
public function __construct($publicKey = null, $privateKey = null,
|
||
|
$params = null, $options = null, $ip = null)
|
||
|
{
|
||
|
if ($publicKey !== null) {
|
||
|
$this->setPublicKey($publicKey);
|
||
|
}
|
||
|
|
||
|
if ($privateKey !== null) {
|
||
|
$this->setPrivateKey($privateKey);
|
||
|
}
|
||
|
|
||
|
if ($ip !== null) {
|
||
|
$this->setIp($ip);
|
||
|
} else if (isset($_SERVER['REMOTE_ADDR'])) {
|
||
|
$this->setIp($_SERVER['REMOTE_ADDR']);
|
||
|
}
|
||
|
|
||
|
if ($params !== null) {
|
||
|
$this->setParams($params);
|
||
|
}
|
||
|
|
||
|
if ($options !== null) {
|
||
|
$this->setOptions($options);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Serialize as string
|
||
|
*
|
||
|
* When the instance is used as a string it will display the recaptcha.
|
||
|
* Since we can't throw exceptions within this method we will trigger
|
||
|
* a user warning instead.
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
public function __toString()
|
||
|
{
|
||
|
try {
|
||
|
$return = $this->getHtml();
|
||
|
} catch (Exception $e) {
|
||
|
$return = '';
|
||
|
trigger_error($e->getMessage(), E_USER_WARNING);
|
||
|
}
|
||
|
|
||
|
return $return;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set the ip property
|
||
|
*
|
||
|
* @param string $ip
|
||
|
* @return Zend_Service_ReCaptcha
|
||
|
*/
|
||
|
public function setIp($ip)
|
||
|
{
|
||
|
$this->_ip = $ip;
|
||
|
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the ip property
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
public function getIp()
|
||
|
{
|
||
|
return $this->_ip;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set a single parameter
|
||
|
*
|
||
|
* @param string $key
|
||
|
* @param string $value
|
||
|
* @return Zend_Service_ReCaptcha
|
||
|
*/
|
||
|
public function setParam($key, $value)
|
||
|
{
|
||
|
$this->_params[$key] = $value;
|
||
|
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set parameters
|
||
|
*
|
||
|
* @param array|Zend_Config $params
|
||
|
* @return Zend_Service_ReCaptcha
|
||
|
* @throws Zend_Service_ReCaptcha_Exception
|
||
|
*/
|
||
|
public function setParams($params)
|
||
|
{
|
||
|
if ($params instanceof Zend_Config) {
|
||
|
$params = $params->toArray();
|
||
|
}
|
||
|
|
||
|
if (is_array($params)) {
|
||
|
foreach ($params as $k => $v) {
|
||
|
$this->setParam($k, $v);
|
||
|
}
|
||
|
} else {
|
||
|
/** @see Zend_Service_ReCaptcha_Exception */
|
||
|
require_once 'Zend/Service/ReCaptcha/Exception.php';
|
||
|
|
||
|
throw new Zend_Service_ReCaptcha_Exception(
|
||
|
'Expected array or Zend_Config object'
|
||
|
);
|
||
|
}
|
||
|
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the parameter array
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
public function getParams()
|
||
|
{
|
||
|
return $this->_params;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get a single parameter
|
||
|
*
|
||
|
* @param string $key
|
||
|
* @return mixed
|
||
|
*/
|
||
|
public function getParam($key)
|
||
|
{
|
||
|
return $this->_params[$key];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set a single option
|
||
|
*
|
||
|
* @param string $key
|
||
|
* @param string $value
|
||
|
* @return Zend_Service_ReCaptcha
|
||
|
*/
|
||
|
public function setOption($key, $value)
|
||
|
{
|
||
|
$this->_options[$key] = $value;
|
||
|
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set options
|
||
|
*
|
||
|
* @param array|Zend_Config $options
|
||
|
* @return Zend_Service_ReCaptcha
|
||
|
* @throws Zend_Service_ReCaptcha_Exception
|
||
|
*/
|
||
|
public function setOptions($options)
|
||
|
{
|
||
|
if ($options instanceof Zend_Config) {
|
||
|
$options = $options->toArray();
|
||
|
}
|
||
|
|
||
|
if (is_array($options)) {
|
||
|
foreach ($options as $k => $v) {
|
||
|
$this->setOption($k, $v);
|
||
|
}
|
||
|
} else {
|
||
|
/** @see Zend_Service_ReCaptcha_Exception */
|
||
|
require_once 'Zend/Service/ReCaptcha/Exception.php';
|
||
|
|
||
|
throw new Zend_Service_ReCaptcha_Exception(
|
||
|
'Expected array or Zend_Config object'
|
||
|
);
|
||
|
}
|
||
|
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the options array
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
public function getOptions()
|
||
|
{
|
||
|
return $this->_options;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get a single option
|
||
|
*
|
||
|
* @param string $key
|
||
|
* @return mixed
|
||
|
*/
|
||
|
public function getOption($key)
|
||
|
{
|
||
|
return $this->_options[$key];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the public key
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
public function getPublicKey()
|
||
|
{
|
||
|
return $this->_publicKey;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set the public key
|
||
|
*
|
||
|
* @param string $publicKey
|
||
|
* @return Zend_Service_ReCaptcha
|
||
|
*/
|
||
|
public function setPublicKey($publicKey)
|
||
|
{
|
||
|
$this->_publicKey = $publicKey;
|
||
|
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the private key
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
public function getPrivateKey()
|
||
|
{
|
||
|
return $this->_privateKey;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set the private key
|
||
|
*
|
||
|
* @param string $privateKey
|
||
|
* @return Zend_Service_ReCaptcha
|
||
|
*/
|
||
|
public function setPrivateKey($privateKey)
|
||
|
{
|
||
|
$this->_privateKey = $privateKey;
|
||
|
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the HTML code for the captcha
|
||
|
*
|
||
|
* This method uses the public key to fetch a recaptcha form.
|
||
|
*
|
||
|
* @return string
|
||
|
* @throws Zend_Service_ReCaptcha_Exception
|
||
|
*/
|
||
|
public function getHtml()
|
||
|
{
|
||
|
if ($this->_publicKey === null) {
|
||
|
/** @see Zend_Service_ReCaptcha_Exception */
|
||
|
require_once 'Zend/Service/ReCaptcha/Exception.php';
|
||
|
|
||
|
throw new Zend_Service_ReCaptcha_Exception('Missing public key');
|
||
|
}
|
||
|
|
||
|
$host = self::API_SERVER;
|
||
|
|
||
|
if ((bool) $this->_params['ssl'] === true) {
|
||
|
$host = self::API_SECURE_SERVER;
|
||
|
}
|
||
|
|
||
|
$htmlBreak = '<br>';
|
||
|
$htmlInputClosing = '>';
|
||
|
|
||
|
if ((bool) $this->_params['xhtml'] === true) {
|
||
|
$htmlBreak = '<br />';
|
||
|
$htmlInputClosing = '/>';
|
||
|
}
|
||
|
|
||
|
$errorPart = '';
|
||
|
|
||
|
if (!empty($this->_params['error'])) {
|
||
|
$errorPart = '&error=' . urlencode($this->_params['error']);
|
||
|
}
|
||
|
|
||
|
$reCaptchaOptions = '';
|
||
|
|
||
|
if (!empty($this->_options)) {
|
||
|
$encoded = Zend_Json::encode($this->_options);
|
||
|
$reCaptchaOptions = <<<SCRIPT
|
||
|
<script type="text/javascript">
|
||
|
var RecaptchaOptions = {$encoded};
|
||
|
</script>
|
||
|
SCRIPT;
|
||
|
}
|
||
|
|
||
|
$return = $reCaptchaOptions;
|
||
|
$return .= <<<HTML
|
||
|
<script type="text/javascript"
|
||
|
src="{$host}/challenge?k={$this->_publicKey}{$errorPart}">
|
||
|
</script>
|
||
|
HTML;
|
||
|
$return .= <<<HTML
|
||
|
<noscript>
|
||
|
<iframe src="{$host}/noscript?k={$this->_publicKey}{$errorPart}"
|
||
|
height="300" width="500" frameborder="0"></iframe>{$htmlBreak}
|
||
|
<textarea name="recaptcha_challenge_field" rows="3" cols="40">
|
||
|
</textarea>
|
||
|
<input type="hidden" name="recaptcha_response_field"
|
||
|
value="manual_challenge"{$htmlInputClosing}
|
||
|
</noscript>
|
||
|
HTML;
|
||
|
|
||
|
return $return;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Post a solution to the verify server
|
||
|
*
|
||
|
* @param string $challengeField
|
||
|
* @param string $responseField
|
||
|
* @return Zend_Http_Response
|
||
|
* @throws Zend_Service_ReCaptcha_Exception
|
||
|
*/
|
||
|
protected function _post($challengeField, $responseField)
|
||
|
{
|
||
|
if ($this->_privateKey === null) {
|
||
|
/** @see Zend_Service_ReCaptcha_Exception */
|
||
|
require_once 'Zend/Service/ReCaptcha/Exception.php';
|
||
|
|
||
|
throw new Zend_Service_ReCaptcha_Exception('Missing private key');
|
||
|
}
|
||
|
|
||
|
if ($this->_ip === null) {
|
||
|
/** @see Zend_Service_ReCaptcha_Exception */
|
||
|
require_once 'Zend/Service/ReCaptcha/Exception.php';
|
||
|
|
||
|
throw new Zend_Service_ReCaptcha_Exception('Missing ip address');
|
||
|
}
|
||
|
|
||
|
if (empty($challengeField)) {
|
||
|
/** @see Zend_Service_ReCaptcha_Exception */
|
||
|
require_once 'Zend/Service/ReCaptcha/Exception.php';
|
||
|
throw new Zend_Service_ReCaptcha_Exception('Missing challenge field');
|
||
|
}
|
||
|
|
||
|
if (empty($responseField)) {
|
||
|
/** @see Zend_Service_ReCaptcha_Exception */
|
||
|
require_once 'Zend/Service/ReCaptcha/Exception.php';
|
||
|
|
||
|
throw new Zend_Service_ReCaptcha_Exception('Missing response field');
|
||
|
}
|
||
|
|
||
|
/* Fetch an instance of the http client */
|
||
|
$httpClient = self::getHttpClient();
|
||
|
|
||
|
$postParams = array('privatekey' => $this->_privateKey,
|
||
|
'remoteip' => $this->_ip,
|
||
|
'challenge' => $challengeField,
|
||
|
'response' => $responseField);
|
||
|
|
||
|
/* Make the POST and return the response */
|
||
|
return $httpClient->setUri(self::VERIFY_SERVER)
|
||
|
->setParameterPost($postParams)
|
||
|
->request(Zend_Http_Client::POST);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Verify the user input
|
||
|
*
|
||
|
* This method calls up the post method and returns a
|
||
|
* Zend_Service_ReCaptcha_Response object.
|
||
|
*
|
||
|
* @param string $challengeField
|
||
|
* @param string $responseField
|
||
|
* @return Zend_Service_ReCaptcha_Response
|
||
|
*/
|
||
|
public function verify($challengeField, $responseField)
|
||
|
{
|
||
|
$response = $this->_post($challengeField, $responseField);
|
||
|
|
||
|
return new Zend_Service_ReCaptcha_Response(null, null, $response);
|
||
|
}
|
||
|
}
|