PageRenderTime 51ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/vendor/zendframework/zendservice-recaptcha/library/ZendService/ReCaptcha/ReCaptcha.php

https://bitbucket.org/juan_sanchez/aiyellow
PHP | 498 lines | 235 code | 67 blank | 196 comment | 20 complexity | 0b760a8669b0a3af09731d0a8231fbaa MD5 | raw file
  1. <?php
  2. /**
  3. * Zend Framework (http://framework.zend.com/)
  4. *
  5. * @link http://github.com/zendframework/zf2 for the canonical source repository
  6. * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
  7. * @license http://framework.zend.com/license/new-bsd New BSD License
  8. * @package Zend_Service
  9. */
  10. namespace ZendService\ReCaptcha;
  11. use Traversable;
  12. use Zend\Http\Client as HttpClient;
  13. use Zend\Http\Request as HttpRequest;
  14. use Zend\Stdlib\ArrayUtils;
  15. /**
  16. * Zend_Service_ReCaptcha
  17. *
  18. * @category Zend
  19. * @package Zend_Service
  20. * @subpackage ReCaptcha
  21. */
  22. class ReCaptcha
  23. {
  24. /**
  25. * URI to the regular API
  26. *
  27. * @var string
  28. */
  29. const API_SERVER = 'http://www.google.com/recaptcha/api';
  30. /**
  31. * URI to the secure API
  32. *
  33. * @var string
  34. */
  35. const API_SECURE_SERVER = 'https://www.google.com/recaptcha/api';
  36. /**
  37. * URI to the verify server
  38. *
  39. * @var string
  40. */
  41. const VERIFY_SERVER = 'http://www.google.com/recaptcha/api/verify';
  42. /**
  43. * Public key used when displaying the captcha
  44. *
  45. * @var string
  46. */
  47. protected $publicKey = null;
  48. /**
  49. * Private key used when verifying user input
  50. *
  51. * @var string
  52. */
  53. protected $privateKey = null;
  54. /**
  55. * Ip address used when verifying user input
  56. *
  57. * @var string
  58. */
  59. protected $ip = null;
  60. /**
  61. * Parameters for the object
  62. *
  63. * @var array
  64. */
  65. protected $params = array(
  66. 'ssl' => false, /* Use SSL or not when generating the recaptcha */
  67. 'error' => null, /* The error message to display in the recaptcha */
  68. 'xhtml' => false /* Enable XHTML output (this will not be XHTML Strict
  69. compliant since the IFRAME is necessary when
  70. Javascript is disabled) */
  71. );
  72. /**
  73. * Options for tailoring reCaptcha
  74. *
  75. * See the different options on http://recaptcha.net/apidocs/captcha/client.html
  76. *
  77. * @var array
  78. */
  79. protected $options = array(
  80. 'theme' => 'red',
  81. 'lang' => 'en',
  82. );
  83. /**
  84. * @var HttpClient
  85. */
  86. protected $httpClient = null;
  87. /**
  88. * Response from the verify server
  89. *
  90. * @var \ZendService\ReCaptcha\Response
  91. */
  92. protected $_response = null;
  93. /**
  94. * Class constructor
  95. *
  96. * @param string $publicKey
  97. * @param string $privateKey
  98. * @param array|Traversable $params
  99. * @param array|Traversable $options
  100. * @param string $ip
  101. */
  102. public function __construct($publicKey = null, $privateKey = null, $params = null, $options = null, $ip = null, HttpClient $httpClient = null)
  103. {
  104. if ($publicKey !== null) {
  105. $this->setPublicKey($publicKey);
  106. }
  107. if ($privateKey !== null) {
  108. $this->setPrivateKey($privateKey);
  109. }
  110. if ($ip !== null) {
  111. $this->setIp($ip);
  112. } elseif (isset($_SERVER['REMOTE_ADDR'])) {
  113. $this->setIp($_SERVER['REMOTE_ADDR']);
  114. }
  115. if ($params !== null) {
  116. $this->setParams($params);
  117. }
  118. if ($options !== null) {
  119. $this->setOptions($options);
  120. }
  121. $this->setHttpClient($httpClient ?: new HttpClient);
  122. }
  123. public function setHttpClient(HttpClient $httpClient)
  124. {
  125. $this->httpClient = $httpClient;
  126. return $this;
  127. }
  128. public function getHttpClient()
  129. {
  130. return $this->httpClient;
  131. }
  132. /**
  133. * Serialize as string
  134. *
  135. * When the instance is used as a string it will display the recaptcha.
  136. * Since we can't throw exceptions within this method we will trigger
  137. * a user warning instead.
  138. *
  139. * @return string
  140. */
  141. public function __toString()
  142. {
  143. try {
  144. $return = $this->getHtml();
  145. } catch (\Exception $e) {
  146. $return = '';
  147. trigger_error($e->getMessage(), E_USER_WARNING);
  148. }
  149. return $return;
  150. }
  151. /**
  152. * Set the ip property
  153. *
  154. * @param string $ip
  155. * @return \ZendService\ReCaptcha\ReCaptcha
  156. */
  157. public function setIp($ip)
  158. {
  159. $this->ip = $ip;
  160. return $this;
  161. }
  162. /**
  163. * Get the ip property
  164. *
  165. * @return string
  166. */
  167. public function getIp()
  168. {
  169. return $this->ip;
  170. }
  171. /**
  172. * Set a single parameter
  173. *
  174. * @param string $key
  175. * @param string $value
  176. * @return \ZendService\ReCaptcha\ReCaptcha
  177. */
  178. public function setParam($key, $value)
  179. {
  180. $this->params[$key] = $value;
  181. return $this;
  182. }
  183. /**
  184. * Set parameters
  185. *
  186. * @param array|Traversable $params
  187. * @return \ZendService\ReCaptcha\ReCaptcha
  188. * @throws \ZendService\ReCaptcha\Exception
  189. */
  190. public function setParams($params)
  191. {
  192. if ($params instanceof Traversable) {
  193. $params = ArrayUtils::iteratorToArray($params);
  194. }
  195. if (!is_array($params)) {
  196. throw new Exception(sprintf(
  197. '%s expects an array or Traversable set of params; received "%s"',
  198. __METHOD__,
  199. (is_object($params) ? get_class($params) : gettype($params))
  200. ));
  201. }
  202. foreach ($params as $k => $v) {
  203. $this->setParam($k, $v);
  204. }
  205. return $this;
  206. }
  207. /**
  208. * Get the parameter array
  209. *
  210. * @return array
  211. */
  212. public function getParams()
  213. {
  214. return $this->params;
  215. }
  216. /**
  217. * Get a single parameter
  218. *
  219. * @param string $key
  220. * @return mixed
  221. */
  222. public function getParam($key)
  223. {
  224. return $this->params[$key];
  225. }
  226. /**
  227. * Set a single option
  228. *
  229. * @param string $key
  230. * @param string $value
  231. * @return \ZendService\ReCaptcha\ReCaptcha
  232. */
  233. public function setOption($key, $value)
  234. {
  235. $this->options[$key] = $value;
  236. return $this;
  237. }
  238. /**
  239. * Set options
  240. *
  241. * @param array|Traversable $options
  242. * @return \ZendService\ReCaptcha\ReCaptcha
  243. * @throws \ZendService\ReCaptcha\Exception
  244. */
  245. public function setOptions($options)
  246. {
  247. if ($options instanceof Traversable) {
  248. $options = ArrayUtils::iteratorToArray($options);
  249. }
  250. if (is_array($options)) {
  251. foreach ($options as $k => $v) {
  252. $this->setOption($k, $v);
  253. }
  254. } else {
  255. throw new Exception(
  256. 'Expected array or Traversable object'
  257. );
  258. }
  259. return $this;
  260. }
  261. /**
  262. * Get the options array
  263. *
  264. * @return array
  265. */
  266. public function getOptions()
  267. {
  268. return $this->options;
  269. }
  270. /**
  271. * Get a single option
  272. *
  273. * @param string $key
  274. * @return mixed
  275. */
  276. public function getOption($key)
  277. {
  278. return $this->options[$key];
  279. }
  280. /**
  281. * Get the public key
  282. *
  283. * @return string
  284. */
  285. public function getPublicKey()
  286. {
  287. return $this->publicKey;
  288. }
  289. /**
  290. * Set the public key
  291. *
  292. * @param string $publicKey
  293. * @return \ZendService\ReCaptcha\ReCaptcha
  294. */
  295. public function setPublicKey($publicKey)
  296. {
  297. $this->publicKey = $publicKey;
  298. return $this;
  299. }
  300. /**
  301. * Get the private key
  302. *
  303. * @return string
  304. */
  305. public function getPrivateKey()
  306. {
  307. return $this->privateKey;
  308. }
  309. /**
  310. * Set the private key
  311. *
  312. * @param string $privateKey
  313. * @return \ZendService\ReCaptcha\ReCaptcha
  314. */
  315. public function setPrivateKey($privateKey)
  316. {
  317. $this->privateKey = $privateKey;
  318. return $this;
  319. }
  320. /**
  321. * Get the HTML code for the captcha
  322. *
  323. * This method uses the public key to fetch a recaptcha form.
  324. *
  325. * @param null|string $name Base name for recaptcha form elements
  326. * @return string
  327. * @throws \ZendService\ReCaptcha\Exception
  328. */
  329. public function getHtml($name = null)
  330. {
  331. if ($this->publicKey === null) {
  332. throw new Exception('Missing public key');
  333. }
  334. $host = self::API_SERVER;
  335. if ((bool) $this->params['ssl'] === true) {
  336. $host = self::API_SECURE_SERVER;
  337. }
  338. $htmlBreak = '<br>';
  339. $htmlInputClosing = '>';
  340. if ((bool) $this->params['xhtml'] === true) {
  341. $htmlBreak = '<br />';
  342. $htmlInputClosing = '/>';
  343. }
  344. $errorPart = '';
  345. if (!empty($this->params['error'])) {
  346. $errorPart = '&error=' . urlencode($this->params['error']);
  347. }
  348. $reCaptchaOptions = '';
  349. if (!empty($this->options)) {
  350. $encoded = \Zend\Json\Json::encode($this->options);
  351. $reCaptchaOptions = <<<SCRIPT
  352. <script type="text/javascript">
  353. var RecaptchaOptions = {$encoded};
  354. </script>
  355. SCRIPT;
  356. }
  357. $challengeField = 'recaptcha_challenge_field';
  358. $responseField = 'recaptcha_response_field';
  359. if (!empty($name)) {
  360. $challengeField = $name . '[' . $challengeField . ']';
  361. $responseField = $name . '[' . $responseField . ']';
  362. }
  363. $return = $reCaptchaOptions;
  364. $return .= <<<HTML
  365. <script type="text/javascript"
  366. src="{$host}/challenge?k={$this->publicKey}{$errorPart}">
  367. </script>
  368. HTML;
  369. $return .= <<<HTML
  370. <noscript>
  371. <iframe src="{$host}/noscript?k={$this->publicKey}{$errorPart}"
  372. height="300" width="500" frameborder="0"></iframe>{$htmlBreak}
  373. <textarea name="{$challengeField}" rows="3" cols="40">
  374. </textarea>
  375. <input type="hidden" name="{$responseField}"
  376. value="manual_challenge"{$htmlInputClosing}
  377. </noscript>
  378. HTML;
  379. return $return;
  380. }
  381. /**
  382. * Post a solution to the verify server
  383. *
  384. * @param string $challengeField
  385. * @param string $responseField
  386. * @return \Zend\Http\Response
  387. * @throws \ZendService\ReCaptcha\Exception
  388. */
  389. protected function post($challengeField, $responseField)
  390. {
  391. if ($this->privateKey === null) {
  392. throw new Exception('Missing private key');
  393. }
  394. if ($this->ip === null) {
  395. throw new Exception('Missing ip address');
  396. }
  397. if (empty($challengeField)) {
  398. throw new Exception('Missing challenge field');
  399. }
  400. if (empty($responseField)) {
  401. throw new Exception('Missing response field');
  402. }
  403. /* Fetch an instance of the http client */
  404. $httpClient = $this->getHttpClient();
  405. $postParams = array('privatekey' => $this->privateKey,
  406. 'remoteip' => $this->ip,
  407. 'challenge' => $challengeField,
  408. 'response' => $responseField);
  409. $request = new HttpRequest;
  410. $request->setUri(self::VERIFY_SERVER);
  411. $request->getPost()->fromArray($postParams);
  412. $request->setMethod(HttpRequest::METHOD_POST);
  413. $httpClient->setEncType($httpClient::ENC_URLENCODED);
  414. return $httpClient->send($request);
  415. }
  416. /**
  417. * Verify the user input
  418. *
  419. * This method calls up the post method and returns a
  420. * Zend_Service_ReCaptcha_Response object.
  421. *
  422. * @param string $challengeField
  423. * @param string $responseField
  424. * @return \ZendService\ReCaptcha\Response
  425. */
  426. public function verify($challengeField, $responseField)
  427. {
  428. $response = $this->post($challengeField, $responseField);
  429. return new Response(null, null, $response);
  430. }
  431. }