PageRenderTime 43ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/blog/core/packages/quip-2.3.1-pl/modCategory/c5d21c5476da1575228a61f46e2e9263/0/quip/model/recaptcha/recaptcha.class.php

https://bitbucket.org/orchdork10159/dnsman.ly
PHP | 271 lines | 154 code | 32 blank | 85 comment | 19 complexity | ae1d4dfa1be0002c3047db4dc617597a MD5 | raw file
  1. <?php
  2. /**
  3. * reCaptcha Integration
  4. *
  5. * Copyright 2009-2010 by Shaun McCormick <shaun@modx.com>
  6. *
  7. * reCaptcha Integration is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by the Free
  9. * Software Foundation; either version 2 of the License, or (at your option) any
  10. * later version.
  11. *
  12. * reCaptcha Integration is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  15. * details.
  16. *
  17. * You should have received a copy of the GNU General Public License along with
  18. * reCaptcha Integration; if not, write to the Free Software Foundation, Inc.,
  19. * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20. *
  21. * @package recaptcha
  22. */
  23. /**
  24. * reCaptcha modX service class.
  25. *
  26. * Based off of recaptchalib.php by Mike Crawford and Ben Maurer. Changes include converting to OOP and making a class.
  27. *
  28. * @package recaptcha
  29. */
  30. class reCaptcha {
  31. const OPT_API_SERVER = 'api_server';
  32. const OPT_API_SECURE_SERVER = 'api_secure_server';
  33. const OPT_API_VERIFY_SERVER = 'api_verify_server';
  34. const OPT_PRIVATE_KEY = 'privateKey';
  35. const OPT_PUBLIC_KEY = 'publicKey';
  36. const OPT_USE_SSL = 'use_ssl';
  37. function __construct(modX &$modx,array $config = array()) {
  38. $this->modx =& $modx;
  39. $this->modx->lexicon->load('quip:recaptcha');
  40. $this->config = array_merge(array(
  41. reCaptcha::OPT_PRIVATE_KEY => $this->modx->getOption('recaptcha.private_key',$config,''),
  42. reCaptcha::OPT_PUBLIC_KEY => $this->modx->getOption('recaptcha.public_key',$config,''),
  43. reCaptcha::OPT_USE_SSL => $this->modx->getOption('recaptcha.use_ssl',$config,false),
  44. reCaptcha::OPT_API_SERVER => 'http://www.google.com/recaptcha/api/',
  45. reCaptcha::OPT_API_SECURE_SERVER => 'https://www.google.com/recaptcha/api/',
  46. reCaptcha::OPT_API_VERIFY_SERVER => 'api-verify.recaptcha.net',
  47. ),$config);
  48. }
  49. /**
  50. * Encodes the given data into a query string format
  51. * @param $data - array of string elements to be encoded
  52. * @return string - encoded request
  53. */
  54. protected function qsencode($data) {
  55. $req = '';
  56. foreach ($data as $key => $value) {
  57. $req .= $key . '=' . urlencode( stripslashes($value) ) . '&';
  58. }
  59. // Cut the last '&'
  60. $req=substr($req,0,strlen($req)-1);
  61. return $req;
  62. }
  63. /**
  64. * Submits an HTTP POST to a reCAPTCHA server
  65. * @param string $host
  66. * @param string $path
  67. * @param array $data
  68. * @param int port
  69. * @return array response
  70. */
  71. protected function httpPost($host, $path, array $data = array(), $port = 80) {
  72. $data['privatekey'] = $this->config[reCaptcha::OPT_PRIVATE_KEY];
  73. $req = $this->qsencode($data);
  74. $http_request = "POST $path HTTP/1.0\r\n";
  75. $http_request .= "Host: $host\r\n";
  76. $http_request .= "Content-Type: application/x-www-form-urlencoded;\r\n";
  77. $http_request .= "Content-Length: " . strlen($req) . "\r\n";
  78. $http_request .= "User-Agent: reCAPTCHA/PHP\r\n";
  79. $http_request .= "\r\n";
  80. $http_request .= $req;
  81. $response = '';
  82. if(false == ($fs = @fsockopen($host, $port, $errno, $errstr, 10))) {
  83. return 'Could not open socket';
  84. }
  85. fwrite($fs, $http_request);
  86. while (!feof($fs)) {
  87. $response .= fgets($fs, 1160); // One TCP-IP packet
  88. }
  89. fclose($fs);
  90. $response = explode("\r\n\r\n", $response, 2);
  91. return $response;
  92. }
  93. /**
  94. * Gets the challenge HTML (javascript and non-javascript version).
  95. * This is called from the browser, and the resulting reCAPTCHA HTML widget
  96. * is embedded within the HTML form it was called from.
  97. * @param string $theme The theme to use
  98. * @param string $error The error given by reCAPTCHA (optional, default is null)
  99. * @param boolean $use_ssl Should the request be made over ssl? (optional, default is false)
  100. * @return string - The HTML to be embedded in the user's form.
  101. */
  102. public function getHtml($theme = 'clean',$error = null) {
  103. if (empty($this->config[reCaptcha::OPT_PUBLIC_KEY])) {
  104. return $this->error($this->modx->lexicon('recaptcha.no_api_key'));
  105. }
  106. /* use ssl or not */
  107. $server = !empty($this->config[reCaptcha::OPT_USE_SSL]) ? $this->config[reCaptcha::OPT_API_SECURE_SERVER] : $this->config[reCaptcha::OPT_API_SERVER];
  108. $errorpart = '';
  109. if ($error) {
  110. $errorpart = "&amp;error=" . $error;
  111. }
  112. $opt = array(
  113. 'theme' => $theme,
  114. 'lang' => $this->modx->getOption('cultureKey',null,'en'),
  115. );
  116. return '<script type="text/javascript">var RecaptchaOptions = '.$this->modx->toJSON($opt).';</script><script type="text/javascript" src="'. $server . 'challenge?k=' . $this->config[reCaptcha::OPT_PUBLIC_KEY] . $errorpart . '"></script>
  117. <noscript>
  118. <iframe src="'. $server . 'noscript?k=' . $this->config[reCaptcha::OPT_PUBLIC_KEY] . $errorpart . '" height="300" width="500" frameborder="0"></iframe><br/>
  119. <textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
  120. <input type="hidden" name="recaptcha_response_field" value="manual_challenge"/>
  121. </noscript>';
  122. }
  123. protected function error($message = '') {
  124. $response = new reCaptchaResponse();
  125. $response->is_valid = false;
  126. $response->error = $message;
  127. return $message;
  128. }
  129. /**
  130. * Calls an HTTP POST function to verify if the user's guess was correct
  131. * @param string $remoteip
  132. * @param string $challenge
  133. * @param string $response
  134. * @param array $extra_params an array of extra variables to post to the server
  135. * @return ReCaptchaResponse
  136. */
  137. public function checkAnswer ($remoteIp, $challenge, $responseField, $extraParams = array()) {
  138. if (empty($this->config[reCaptcha::OPT_PRIVATE_KEY])) {
  139. return $this->error($this->modx->lexicon('recaptcha.no_api_key'));
  140. }
  141. if (empty($remoteIp)) {
  142. return $this->error($this->modx->lexicon('recaptcha.no_remote_ip'));
  143. }
  144. //discard spam submissions
  145. if (empty($challenge) || empty($responseField)) {
  146. return $this->error($this->modx->lexicon('recaptcha.empty_answer'));
  147. }
  148. $verifyServer = $this->config[reCaptcha::OPT_API_VERIFY_SERVER];
  149. $response = $this->httpPost($verifyServer,"/verify",array (
  150. 'remoteip' => $remoteIp,
  151. 'challenge' => $challenge,
  152. 'response' => $responseField,
  153. ) + $extraParams);
  154. $answers = explode("\n",$response[1]);
  155. $response = new reCaptchaResponse();
  156. if (trim($answers[0]) == 'true') {
  157. $response->is_valid = true;
  158. } else {
  159. $response->is_valid = false;
  160. $response->error = $answers [1];
  161. }
  162. return $response;
  163. }
  164. /**
  165. * gets a URL where the user can sign up for reCAPTCHA. If your application
  166. * has a configuration page where you enter a key, you should provide a link
  167. * using this function.
  168. * @param string $domain The domain where the page is hosted
  169. * @param string $appname The name of your application
  170. */
  171. public function getSignupUrl ($domain = null, $appname = null) {
  172. return "http://recaptcha.net/api/getkey?" . $this->qsencode(array ('domain' => $domain, 'app' => $appname));
  173. }
  174. protected function aesPad($val) {
  175. $block_size = 16;
  176. $numpad = $block_size - (strlen ($val) % $block_size);
  177. return str_pad($val, strlen ($val) + $numpad, chr($numpad));
  178. }
  179. /* Mailhide related code */
  180. protected function aesEncrypt($val,$ky) {
  181. if (!function_exists("mcrypt_encrypt")) {
  182. return $this->error($this->modx->lexicon('recaptcha.mailhide_no_mcrypt'));
  183. }
  184. $mode=MCRYPT_MODE_CBC;
  185. $enc=MCRYPT_RIJNDAEL_128;
  186. $val= $this->aesPad($val);
  187. return mcrypt_encrypt($enc, $ky, $val, $mode, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
  188. }
  189. protected function mailhideUrlbase64 ($x) {
  190. return strtr(base64_encode ($x), '+/', '-_');
  191. }
  192. /* gets the reCAPTCHA Mailhide url for a given email, public key and private key */
  193. public function mailhideUrl($email) {
  194. if (empty($this->config[reCaptcha::OPT_PUBLIC_KEY]) || empty($this->config[reCaptcha::OPT_PRIVATE_KEY])) {
  195. return $this->error($this->modx->lexicon('recaptcha.mailhide_no_api_key'));
  196. }
  197. $ky = pack('H*',$this->config[reCaptcha::OPT_PRIVATE_KEY]);
  198. $cryptmail = $this->aesEncrypt($email, $ky);
  199. return 'http://mailhide.recaptcha.net/d?k='
  200. . $this->config[reCaptcha::OPT_PUBLIC_KEY]
  201. . '&c=' . $this->mailhideUrlbase64($cryptmail);
  202. }
  203. /**
  204. * gets the parts of the email to expose to the user.
  205. * eg, given johndoe@example,com return ["john", "example.com"].
  206. * the email is then displayed as john...@example.com
  207. */
  208. public function mailhideEmailParts ($email) {
  209. $arr = preg_split("/@/", $email);
  210. if (strlen($arr[0]) <= 4) {
  211. $arr[0] = substr($arr[0], 0, 1);
  212. } else if (strlen ($arr[0]) <= 6) {
  213. $arr[0] = substr($arr[0], 0, 3);
  214. } else {
  215. $arr[0] = substr($arr[0], 0, 4);
  216. }
  217. return $arr;
  218. }
  219. /**
  220. * Gets html to display an email address given a public an private key.
  221. * to get a key, go to:
  222. *
  223. * http://mailhide.recaptcha.net/apikey
  224. */
  225. public function mailhideHtml($email) {
  226. $emailparts = $this->mailhideEmailParts($email);
  227. $url = $this->mailhideUrl($email);
  228. return htmlentities($emailparts[0]) . "<a href='" . htmlentities ($url) .
  229. "' onclick=\"window.open('" . htmlentities ($url) . "', '', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=300'); return false;\" title=\"Reveal this e-mail address\">...</a>@" . htmlentities ($emailparts [1]);
  230. }
  231. }
  232. /**
  233. * A reCaptchaResponse is returned from reCaptcha::check_answer()
  234. */
  235. class reCaptchaResponse {
  236. public $is_valid;
  237. public $error;
  238. }