File indexing completed on 2025-01-26 05:25:30
0001 <?php 0002 /** 0003 * Zend Framework 0004 * 0005 * LICENSE 0006 * 0007 * This source file is subject to the new BSD license that is bundled 0008 * with this package in the file LICENSE.txt. 0009 * It is also available through the world-wide-web at this URL: 0010 * http://framework.zend.com/license/new-bsd 0011 * If you did not receive a copy of the license and are unable to 0012 * obtain it through the world-wide-web, please send an email 0013 * to license@zend.com so we can send you a copy immediately. 0014 * 0015 * @category Zend 0016 * @package Zend_Service 0017 * @subpackage ReCaptcha 0018 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0019 * @license http://framework.zend.com/license/new-bsd New BSD License 0020 */ 0021 0022 /** @see Zend_Service_Abstract */ 0023 // require_once 'Zend/Service/Abstract.php'; 0024 0025 /** @see Zend_Json */ 0026 // require_once 'Zend/Json.php'; 0027 0028 /** @see Zend_Service_ReCaptcha_Response */ 0029 // require_once 'Zend/Service/ReCaptcha/Response.php'; 0030 0031 /** 0032 * Zend_Service_ReCaptcha 0033 * 0034 * @category Zend 0035 * @package Zend_Service 0036 * @subpackage ReCaptcha 0037 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0038 * @license http://framework.zend.com/license/new-bsd New BSD License 0039 * @version $Id$ 0040 */ 0041 class Zend_Service_ReCaptcha extends Zend_Service_Abstract 0042 { 0043 /** 0044 * URI to the regular API 0045 * 0046 * @var string 0047 */ 0048 const API_SERVER = 'http://www.google.com/recaptcha/api'; 0049 0050 /** 0051 * URI to the secure API 0052 * 0053 * @var string 0054 */ 0055 const API_SECURE_SERVER = 'https://www.google.com/recaptcha/api'; 0056 0057 /** 0058 * URI to the verify server 0059 * 0060 * @var string 0061 */ 0062 const VERIFY_SERVER = 'http://www.google.com/recaptcha/api/verify'; 0063 0064 /** 0065 * Public key used when displaying the captcha 0066 * 0067 * @var string 0068 */ 0069 protected $_publicKey = null; 0070 0071 /** 0072 * Private key used when verifying user input 0073 * 0074 * @var string 0075 */ 0076 protected $_privateKey = null; 0077 0078 /** 0079 * Ip address used when verifying user input 0080 * 0081 * @var string 0082 */ 0083 protected $_ip = null; 0084 0085 /** 0086 * Parameters for the object 0087 * 0088 * @var array 0089 */ 0090 protected $_params = array( 0091 'ssl' => false, /* Use SSL or not when generating the recaptcha */ 0092 'error' => null, /* The error message to display in the recaptcha */ 0093 'xhtml' => false /* Enable XHTML output (this will not be XHTML Strict 0094 compliant since the IFRAME is necessary when 0095 Javascript is disabled) */ 0096 ); 0097 0098 /** 0099 * Options for tailoring reCaptcha 0100 * 0101 * See the different options on http://recaptcha.net/apidocs/captcha/client.html 0102 * 0103 * @var array 0104 */ 0105 protected $_options = array( 0106 'theme' => 'red', 0107 'lang' => 'en', 0108 'custom_translations' => array(), 0109 ); 0110 0111 /** 0112 * Response from the verify server 0113 * 0114 * @var Zend_Service_ReCaptcha_Response 0115 */ 0116 protected $_response = null; 0117 0118 /** 0119 * Class constructor 0120 * 0121 * @param string $publicKey 0122 * @param string $privateKey 0123 * @param array $params 0124 * @param array $options 0125 * @param string $ip 0126 * @param array|Zend_Config $params 0127 */ 0128 public function __construct($publicKey = null, $privateKey = null, 0129 $params = null, $options = null, $ip = null) 0130 { 0131 if ($publicKey !== null) { 0132 $this->setPublicKey($publicKey); 0133 } 0134 0135 if ($privateKey !== null) { 0136 $this->setPrivateKey($privateKey); 0137 } 0138 0139 if ($ip !== null) { 0140 $this->setIp($ip); 0141 } else if (isset($_SERVER['REMOTE_ADDR'])) { 0142 $this->setIp($_SERVER['REMOTE_ADDR']); 0143 } 0144 0145 if ($params !== null) { 0146 $this->setParams($params); 0147 } 0148 0149 if ($options !== null) { 0150 $this->setOptions($options); 0151 } 0152 } 0153 0154 /** 0155 * Serialize as string 0156 * 0157 * When the instance is used as a string it will display the recaptcha. 0158 * Since we can't throw exceptions within this method we will trigger 0159 * a user warning instead. 0160 * 0161 * @return string 0162 */ 0163 public function __toString() 0164 { 0165 try { 0166 $return = $this->getHtml(); 0167 } catch (Exception $e) { 0168 $return = ''; 0169 trigger_error($e->getMessage(), E_USER_WARNING); 0170 } 0171 0172 return $return; 0173 } 0174 0175 /** 0176 * Set the ip property 0177 * 0178 * @param string $ip 0179 * @return Zend_Service_ReCaptcha 0180 */ 0181 public function setIp($ip) 0182 { 0183 $this->_ip = $ip; 0184 0185 return $this; 0186 } 0187 0188 /** 0189 * Get the ip property 0190 * 0191 * @return string 0192 */ 0193 public function getIp() 0194 { 0195 return $this->_ip; 0196 } 0197 0198 /** 0199 * Set a single parameter 0200 * 0201 * @param string $key 0202 * @param string $value 0203 * @return Zend_Service_ReCaptcha 0204 */ 0205 public function setParam($key, $value) 0206 { 0207 $this->_params[$key] = $value; 0208 0209 return $this; 0210 } 0211 0212 /** 0213 * Set parameters 0214 * 0215 * @param array|Zend_Config $params 0216 * @return Zend_Service_ReCaptcha 0217 * @throws Zend_Service_ReCaptcha_Exception 0218 */ 0219 public function setParams($params) 0220 { 0221 if ($params instanceof Zend_Config) { 0222 $params = $params->toArray(); 0223 } 0224 0225 if (is_array($params)) { 0226 foreach ($params as $k => $v) { 0227 $this->setParam($k, $v); 0228 } 0229 } else { 0230 /** @see Zend_Service_ReCaptcha_Exception */ 0231 // require_once 'Zend/Service/ReCaptcha/Exception.php'; 0232 0233 throw new Zend_Service_ReCaptcha_Exception( 0234 'Expected array or Zend_Config object' 0235 ); 0236 } 0237 0238 return $this; 0239 } 0240 0241 /** 0242 * Get the parameter array 0243 * 0244 * @return array 0245 */ 0246 public function getParams() 0247 { 0248 return $this->_params; 0249 } 0250 0251 /** 0252 * Get a single parameter 0253 * 0254 * @param string $key 0255 * @return mixed 0256 */ 0257 public function getParam($key) 0258 { 0259 return $this->_params[$key]; 0260 } 0261 0262 /** 0263 * Set a single option 0264 * 0265 * @param string $key 0266 * @param string $value 0267 * @return Zend_Service_ReCaptcha 0268 */ 0269 public function setOption($key, $value) 0270 { 0271 $this->_options[$key] = $value; 0272 0273 return $this; 0274 } 0275 0276 /** 0277 * Set options 0278 * 0279 * @param array|Zend_Config $options 0280 * @return Zend_Service_ReCaptcha 0281 * @throws Zend_Service_ReCaptcha_Exception 0282 */ 0283 public function setOptions($options) 0284 { 0285 if ($options instanceof Zend_Config) { 0286 $options = $options->toArray(); 0287 } 0288 0289 if (is_array($options)) { 0290 foreach ($options as $k => $v) { 0291 $this->setOption($k, $v); 0292 } 0293 } else { 0294 /** @see Zend_Service_ReCaptcha_Exception */ 0295 // require_once 'Zend/Service/ReCaptcha/Exception.php'; 0296 0297 throw new Zend_Service_ReCaptcha_Exception( 0298 'Expected array or Zend_Config object' 0299 ); 0300 } 0301 0302 return $this; 0303 } 0304 0305 /** 0306 * Get the options array 0307 * 0308 * @return array 0309 */ 0310 public function getOptions() 0311 { 0312 return $this->_options; 0313 } 0314 0315 /** 0316 * Get a single option 0317 * 0318 * @param string $key 0319 * @return mixed 0320 */ 0321 public function getOption($key) 0322 { 0323 return $this->_options[$key]; 0324 } 0325 0326 /** 0327 * Get the public key 0328 * 0329 * @return string 0330 */ 0331 public function getPublicKey() 0332 { 0333 return $this->_publicKey; 0334 } 0335 0336 /** 0337 * Set the public key 0338 * 0339 * @param string $publicKey 0340 * @return Zend_Service_ReCaptcha 0341 */ 0342 public function setPublicKey($publicKey) 0343 { 0344 $this->_publicKey = $publicKey; 0345 0346 return $this; 0347 } 0348 0349 /** 0350 * Get the private key 0351 * 0352 * @return string 0353 */ 0354 public function getPrivateKey() 0355 { 0356 return $this->_privateKey; 0357 } 0358 0359 /** 0360 * Set the private key 0361 * 0362 * @param string $privateKey 0363 * @return Zend_Service_ReCaptcha 0364 */ 0365 public function setPrivateKey($privateKey) 0366 { 0367 $this->_privateKey = $privateKey; 0368 0369 return $this; 0370 } 0371 0372 /** 0373 * Get the HTML code for the captcha 0374 * 0375 * This method uses the public key to fetch a recaptcha form. 0376 * 0377 * @param null|string $name Base name for recaptcha form elements 0378 * @return string 0379 * @throws Zend_Service_ReCaptcha_Exception 0380 */ 0381 public function getHtml($name = null) 0382 { 0383 if ($this->_publicKey === null) { 0384 /** @see Zend_Service_ReCaptcha_Exception */ 0385 // require_once 'Zend/Service/ReCaptcha/Exception.php'; 0386 0387 throw new Zend_Service_ReCaptcha_Exception('Missing public key'); 0388 } 0389 0390 $host = self::API_SERVER; 0391 0392 if ((bool) $this->_params['ssl'] === true) { 0393 $host = self::API_SECURE_SERVER; 0394 } 0395 0396 $htmlBreak = '<br>'; 0397 $htmlInputClosing = '>'; 0398 0399 if ((bool) $this->_params['xhtml'] === true) { 0400 $htmlBreak = '<br />'; 0401 $htmlInputClosing = '/>'; 0402 } 0403 0404 $errorPart = ''; 0405 0406 if (!empty($this->_params['error'])) { 0407 $errorPart = '&error=' . urlencode($this->_params['error']); 0408 } 0409 0410 $reCaptchaOptions = ''; 0411 0412 if (!empty($this->_options)) { 0413 $encoded = Zend_Json::encode($this->_options); 0414 $reCaptchaOptions = <<<SCRIPT 0415 <script type="text/javascript"> 0416 var RecaptchaOptions = {$encoded}; 0417 </script> 0418 SCRIPT; 0419 } 0420 $challengeField = 'recaptcha_challenge_field'; 0421 $responseField = 'recaptcha_response_field'; 0422 if (!empty($name)) { 0423 $challengeField = $name . '[' . $challengeField . ']'; 0424 $responseField = $name . '[' . $responseField . ']'; 0425 } 0426 0427 $return = $reCaptchaOptions; 0428 $return .= <<<HTML 0429 <script type="text/javascript" 0430 src="{$host}/challenge?k={$this->_publicKey}{$errorPart}"> 0431 </script> 0432 HTML; 0433 $return .= <<<HTML 0434 <noscript> 0435 <iframe src="{$host}/noscript?k={$this->_publicKey}{$errorPart}" 0436 height="300" width="500" frameborder="0"></iframe>{$htmlBreak} 0437 <textarea name="{$challengeField}" rows="3" cols="40"> 0438 </textarea> 0439 <input type="hidden" name="{$responseField}" 0440 value="manual_challenge"{$htmlInputClosing} 0441 </noscript> 0442 HTML; 0443 0444 return $return; 0445 } 0446 0447 /** 0448 * Post a solution to the verify server 0449 * 0450 * @param string $challengeField 0451 * @param string $responseField 0452 * @return Zend_Http_Response 0453 * @throws Zend_Service_ReCaptcha_Exception 0454 */ 0455 protected function _post($challengeField, $responseField) 0456 { 0457 if ($this->_privateKey === null) { 0458 /** @see Zend_Service_ReCaptcha_Exception */ 0459 // require_once 'Zend/Service/ReCaptcha/Exception.php'; 0460 0461 throw new Zend_Service_ReCaptcha_Exception('Missing private key'); 0462 } 0463 0464 if ($this->_ip === null) { 0465 /** @see Zend_Service_ReCaptcha_Exception */ 0466 // require_once 'Zend/Service/ReCaptcha/Exception.php'; 0467 0468 throw new Zend_Service_ReCaptcha_Exception('Missing ip address'); 0469 } 0470 0471 /* Fetch an instance of the http client */ 0472 $httpClient = self::getHttpClient(); 0473 $httpClient->resetParameters(true); 0474 0475 $postParams = array('privatekey' => $this->_privateKey, 0476 'remoteip' => $this->_ip, 0477 'challenge' => $challengeField, 0478 'response' => $responseField); 0479 0480 /* Make the POST and return the response */ 0481 return $httpClient->setUri(self::VERIFY_SERVER) 0482 ->setParameterPost($postParams) 0483 ->request(Zend_Http_Client::POST); 0484 } 0485 0486 /** 0487 * Verify the user input 0488 * 0489 * This method calls up the post method and returns a 0490 * Zend_Service_ReCaptcha_Response object. 0491 * 0492 * @param string $challengeField 0493 * @param string $responseField 0494 * @return Zend_Service_ReCaptcha_Response 0495 */ 0496 public function verify($challengeField, $responseField) 0497 { 0498 $response = $this->_post($challengeField, $responseField); 0499 0500 return new Zend_Service_ReCaptcha_Response(null, null, $response); 0501 } 0502 }