/lib/recaptchalib.php

  1. <?php 
  2. /** 
  3. * This is a PHP library that handles calling reCAPTCHA. 
  4. * - Documentation and latest version 
  5. * http://recaptcha.net/plugins/php/ 
  6. * - Get a reCAPTCHA API Key 
  7. * https://www.google.com/recaptcha/admin/create 
  8. * - Discussion group 
  9. * http://groups.google.com/group/recaptcha 
  10. * 
  11. * Copyright (c) 2007 reCAPTCHA -- http://recaptcha.net 
  12. * AUTHORS: 
  13. * Mike Crawford 
  14. * Ben Maurer 
  15. * 
  16. * Permission is hereby granted, free of charge, to any person obtaining a copy 
  17. * of this software and associated documentation files (the "Software"), to deal 
  18. * in the Software without restriction, including without limitation the rights 
  19. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
  20. * copies of the Software, and to permit persons to whom the Software is 
  21. * furnished to do so, subject to the following conditions: 
  22. * 
  23. * The above copyright notice and this permission notice shall be included in 
  24. * all copies or substantial portions of the Software. 
  25. * 
  26. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
  27. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,  
  28. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
  29. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
  30. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,  
  31. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
  32. * THE SOFTWARE. 
  33. */ 
  34.  
  35. /** 
  36. * Encodes the given data into a query string format 
  37. * @param $data - array of string elements to be encoded 
  38. * @return string - encoded request 
  39. */ 
  40. function gglcptch_recaptcha_qsencode ($data) { 
  41. $req = ""; 
  42. foreach ( $data as $key => $value ) 
  43. $req .= $key . '=' . urlencode( stripslashes($value) ) . '&'; 
  44.  
  45. // Cut the last '&' 
  46. $req=substr($req, 0, strlen($req)-1); 
  47. return $req; 
  48.  
  49. /** 
  50. * Submits an HTTP POST to a reCAPTCHA server 
  51. * @param string $host 
  52. * @param string $path 
  53. * @param array $data 
  54. * @param int port 
  55. * @return array response 
  56. */ 
  57. function gglcptch_recaptcha_http_post($host, $path, $data, $port = 80) { 
  58.  
  59. $req = gglcptch_recaptcha_qsencode ($data); 
  60.  
  61. $http_request = "POST $path HTTP/1.0\r\n"; 
  62. $http_request .= "Host: $host\r\n"; 
  63. $http_request .= "Content-Type: application/x-www-form-urlencoded;\r\n"; 
  64. $http_request .= "Content-Length: " . strlen($req) . "\r\n"; 
  65. $http_request .= "User-Agent: reCAPTCHA/PHP\r\n"; 
  66. $http_request .= "\r\n"; 
  67. $http_request .= $req; 
  68.  
  69. $response = ''; 
  70. if( false == ( $fs = @fsockopen($host, $port, $errno, $errstr, 10) ) ) { 
  71. die ('Could not open socket'); 
  72.  
  73. fwrite($fs, $http_request); 
  74.  
  75. while ( !feof($fs) ) 
  76. $response .= fgets($fs, 1160); // One TCP-IP packet 
  77. fclose($fs); 
  78. $response = explode("\r\n\r\n", $response, 2); 
  79.  
  80. return $response; 
  81.  
  82. /** 
  83. * Gets the challenge HTML (javascript and non-javascript version). 
  84. * This is called from the browser, and the resulting reCAPTCHA HTML widget 
  85. * is embedded within the HTML form it was called from. 
  86. * @param string $pubkey A public key for reCAPTCHA 
  87. * @param string $error The error given by reCAPTCHA (optional, default is null) 
  88. * @param boolean $use_ssl Should the request be made over ssl? (optional, default is false) 
  89. * @return string - The HTML to be embedded in the user's form. 
  90. */ 
  91. function gglcptch_recaptcha_get_html ($pubkey, $error = null, $use_ssl = false) 
  92. if ($pubkey == null || $pubkey == '') { 
  93. die ("To use reCAPTCHA you must get an API key from <a href='https://www.google.com/recaptcha/admin/create'>https://www.google.com/recaptcha/admin/create</a>"); 
  94.  
  95. if ($use_ssl) { 
  96. $server = "https://www.google.com/recaptcha/api"; 
  97. } else { 
  98. $server = "http://www.google.com/recaptcha/api"; 
  99.  
  100. $errorpart = ""; 
  101. if ($error) { 
  102. $errorpart = "&error=" . $error; 
  103. return '<noscript> 
  104. <iframe src="'. $server . '/noscript?k=' . $pubkey . $errorpart . '" height="300" width="320" frameborder="0"></iframe><br/> 
  105. <textarea name="recaptcha_challenge_field" rows="3" cols="40" style="width: 320px !important; border: 1px solid #333 !important; resize: none !important;"></textarea> 
  106. <input type="hidden" name="recaptcha_response_field" value="manual_challenge"/> 
  107. </noscript>'; 
  108.  
  109. /** 
  110. * A gglcptch_ReCaptchaResponse is returned from gglcptch_recaptcha_check_answer() 
  111. */ 
  112. class gglcptch_ReCaptchaResponse { 
  113. var $is_valid; 
  114. var $error; 
  115.  
  116. /** 
  117. * Calls an HTTP POST function to verify if the user's guess was correct 
  118. * @param string $privkey 
  119. * @param string $remoteip 
  120. * @param string $challenge 
  121. * @param string $response 
  122. * @param array $extra_params an array of extra variables to post to the server 
  123. * @return gglcptch_ReCaptchaResponse 
  124. */ 
  125. function gglcptch_recaptcha_check_answer ($privkey, $remoteip, $challenge, $response, $extra_params = array()) 
  126. if ($privkey == null || $privkey == '') { 
  127. die ("To use reCAPTCHA you must get an API key from <a href='https://www.google.com/recaptcha/admin/create'>https://www.google.com/recaptcha/admin/create</a>"); 
  128.  
  129. if ($remoteip == null || $remoteip == '') { 
  130. die ("For security reasons, you must pass the remote ip to reCAPTCHA"); 
  131.  
  132.  
  133.  
  134. //discard spam submissions 
  135. if ($challenge == null || strlen($challenge) == 0 || $response == null || strlen($response) == 0) { 
  136. $recaptcha_response = new gglcptch_ReCaptchaResponse(); 
  137. $recaptcha_response->is_valid = false; 
  138. $recaptcha_response->error = 'incorrect-captcha-sol'; 
  139. return $recaptcha_response; 
  140.  
  141. $response = gglcptch_recaptcha_http_post ("www.google.com", "/recaptcha/api/verify",  
  142. array ( 
  143. 'privatekey' => $privkey,  
  144. 'remoteip' => $remoteip,  
  145. 'challenge' => $challenge,  
  146. 'response' => $response 
  147. ) + $extra_params 
  148. ); 
  149.  
  150. $answers = explode ("\n", $response [1]); 
  151. $recaptcha_response = new gglcptch_ReCaptchaResponse(); 
  152.  
  153. if (trim ($answers [0]) == 'true') { 
  154. $recaptcha_response->is_valid = true; 
  155. else { 
  156. $recaptcha_response->is_valid = false; 
  157. $recaptcha_response->error = $answers [1]; 
  158. return $recaptcha_response; 
  159.  
  160.  
  161. /** 
  162. * gets a URL where the user can sign up for reCAPTCHA. If your application 
  163. * has a configuration page where you enter a key, you should provide a link 
  164. * using this function. 
  165. * @param string $domain The domain where the page is hosted 
  166. * @param string $appname The name of your application 
  167. */ 
  168. function gglcptch_recaptcha_get_signup_url ($domain = null, $appname = null) { 
  169. return "https://www.google.com/recaptcha/admin/create?" . gglcptch_recaptcha_qsencode (array ('domains' => $domain, 'app' => $appname)); 
  170.  
  171. function gglcptch_recaptcha_aes_pad($val) { 
  172. $block_size = 16; 
  173. $numpad = $block_size - (strlen ($val) % $block_size); 
  174. return str_pad($val, strlen ($val) + $numpad, chr($numpad)); 
  175.  
  176. /** Mailhide related code */ 
  177.  
  178. function gglcptch_recaptcha_aes_encrypt($val, $ky) { 
  179. if (! function_exists ("mcrypt_encrypt")) { 
  180. die ("To use reCAPTCHA Mailhide, you need to have the mcrypt php module installed."); 
  181. $mode=MCRYPT_MODE_CBC; 
  182. $enc=MCRYPT_RIJNDAEL_128; 
  183. $val=gglcptch_recaptcha_aes_pad($val); 
  184. return mcrypt_encrypt($enc, $ky, $val, $mode, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"); 
  185.  
  186.  
  187. function gglcptch_recaptcha_mailhide_urlbase64 ($x) { 
  188. return strtr(base64_encode ($x), '+/', '-_'); 
  189.  
  190. /** gets the reCAPTCHA Mailhide url for a given email, public key and private key */ 
  191. function gglcptch_recaptcha_mailhide_url($pubkey, $privkey, $email) { 
  192. if ($pubkey == '' || $pubkey == null || $privkey == "" || $privkey == null) { 
  193. die ("To use reCAPTCHA Mailhide, you have to sign up for a public and private key, " . 
  194. "you can do so at <a href='http://www.google.com/recaptcha/mailhide/apikey'>http://www.google.com/recaptcha/mailhide/apikey</a>"); 
  195.  
  196.  
  197. $ky = pack('H*', $privkey); 
  198. $cryptmail = gglcptch_recaptcha_aes_encrypt ($email, $ky); 
  199.  
  200. return "http://www.google.com/recaptcha/mailhide/d?k=" . $pubkey . "&c=" . gglcptch_recaptcha_mailhide_urlbase64 ($cryptmail); 
  201.  
  202. /** 
  203. * gets the parts of the email to expose to the user. 
  204. * eg, given johndoe@example, com return ["john", "example.com"]. 
  205. * the email is then displayed as john...@example.com 
  206. */ 
  207. function gglcptch_recaptcha_mailhide_email_parts ($email) { 
  208. $arr = preg_split("/@/", $email ); 
  209.  
  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. return $arr; 
  217.  
  218. /** 
  219. * Gets html to display an email address given a public an private key. 
  220. * to get a key, go to: 
  221. * 
  222. * http://www.google.com/recaptcha/mailhide/apikey 
  223. */ 
  224. function gglcptch_recaptcha_mailhide_html($pubkey, $privkey, $email) { 
  225. $emailparts = gglcptch_recaptcha_mailhide_email_parts ($email); 
  226. $url = gglcptch_recaptcha_mailhide_url ($pubkey, $privkey, $email); 
  227.  
  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. ?> 
.