|
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 * http://recaptcha.net/api/getkey |
|
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 * The reCAPTCHA server URL's |
|
37 */ |
|
38 define("RECAPTCHA_API_SERVER", "http://api.recaptcha.net"); |
|
39 define("RECAPTCHA_API_SECURE_SERVER", "https://api-secure.recaptcha.net"); |
|
40 define("RECAPTCHA_VERIFY_SERVER", "api-verify.recaptcha.net"); |
|
41 |
|
42 /** |
|
43 * Encodes the given data into a query string format |
|
44 * @param $data - array of string elements to be encoded |
|
45 * @return string - encoded request |
|
46 */ |
|
47 function _recaptcha_qsencode ($data) { |
|
48 $req = ""; |
|
49 foreach ( $data as $key => $value ) |
|
50 $req .= $key . '=' . urlencode( stripslashes($value) ) . '&'; |
|
51 |
|
52 // Cut the last '&' |
|
53 $req=substr($req,0,strlen($req)-1); |
|
54 return $req; |
|
55 } |
|
56 |
|
57 |
|
58 |
|
59 /** |
|
60 * Submits an HTTP POST to a reCAPTCHA server |
|
61 * @param string $host |
|
62 * @param string $path |
|
63 * @param array $data |
|
64 * @param int port |
|
65 * @return array response |
|
66 */ |
|
67 function _recaptcha_http_post($host, $path, $data, $port = 80) { |
|
68 |
|
69 $req = _recaptcha_qsencode ($data); |
|
70 |
|
71 $http_request = "POST $path HTTP/1.0\r\n"; |
|
72 $http_request .= "Host: $host\r\n"; |
|
73 $http_request .= "Content-Type: application/x-www-form-urlencoded;\r\n"; |
|
74 $http_request .= "Content-Length: " . strlen($req) . "\r\n"; |
|
75 $http_request .= "User-Agent: reCAPTCHA/PHP\r\n"; |
|
76 $http_request .= "\r\n"; |
|
77 $http_request .= $req; |
|
78 |
|
79 $response = ''; |
|
80 if( false == ( $fs = @fsockopen($host, $port, $errno, $errstr, 10) ) ) { |
|
81 die ('Could not open socket'); |
|
82 } |
|
83 |
|
84 fwrite($fs, $http_request); |
|
85 |
|
86 while ( !feof($fs) ) |
|
87 $response .= fgets($fs, 1160); // One TCP-IP packet |
|
88 fclose($fs); |
|
89 $response = explode("\r\n\r\n", $response, 2); |
|
90 |
|
91 return $response; |
|
92 } |
|
93 |
|
94 |
|
95 |
|
96 /** |
|
97 * Gets the challenge HTML (javascript and non-javascript version). |
|
98 * This is called from the browser, and the resulting reCAPTCHA HTML widget |
|
99 * is embedded within the HTML form it was called from. |
|
100 * @param string $pubkey A public key for reCAPTCHA |
|
101 * @param string $error The error given by reCAPTCHA (optional, default is null) |
|
102 * @param boolean $use_ssl Should the request be made over ssl? (optional, default is false) |
|
103 |
|
104 * @return string - The HTML to be embedded in the user's form. |
|
105 */ |
|
106 function recaptcha_get_html ($pubkey, $error = null, $use_ssl = false) |
|
107 { |
|
108 if ($pubkey == null || $pubkey == '') { |
|
109 die ("To use reCAPTCHA you must get an API key from <a href='http://recaptcha.net/api/getkey'>http://recaptcha.net/api/getkey</a>"); |
|
110 } |
|
111 |
|
112 if ($use_ssl) { |
|
113 $server = RECAPTCHA_API_SECURE_SERVER; |
|
114 } else { |
|
115 $server = RECAPTCHA_API_SERVER; |
|
116 } |
|
117 |
|
118 $errorpart = ""; |
|
119 if ($error) { |
|
120 $errorpart = "&error=" . $error; |
|
121 } |
|
122 return '<script type="text/javascript" src="'. $server . '/challenge?k=' . $pubkey . $errorpart . '"></script> |
|
123 |
|
124 <noscript> |
|
125 <iframe src="'. $server . '/noscript?k=' . $pubkey . $errorpart . '" height="300" width="500" frameborder="0"></iframe><br/> |
|
126 <textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea> |
|
127 <input type="hidden" name="recaptcha_response_field" value="manual_challenge"/> |
|
128 </noscript>'; |
|
129 } |
|
130 |
|
131 |
|
132 |
|
133 |
|
134 /** |
|
135 * A ReCaptchaResponse is returned from recaptcha_check_answer() |
|
136 */ |
|
137 class ReCaptchaResponse { |
|
138 var $is_valid; |
|
139 var $error; |
|
140 } |
|
141 |
|
142 |
|
143 /** |
|
144 * Calls an HTTP POST function to verify if the user's guess was correct |
|
145 * @param string $privkey |
|
146 * @param string $remoteip |
|
147 * @param string $challenge |
|
148 * @param string $response |
|
149 * @param array $extra_params an array of extra variables to post to the server |
|
150 * @return ReCaptchaResponse |
|
151 */ |
|
152 function recaptcha_check_answer ($privkey, $remoteip, $challenge, $response, $extra_params = array()) |
|
153 { |
|
154 if ($privkey == null || $privkey == '') { |
|
155 die ("To use reCAPTCHA you must get an API key from <a href='http://recaptcha.net/api/getkey'>http://recaptcha.net/api/getkey</a>"); |
|
156 } |
|
157 |
|
158 if ($remoteip == null || $remoteip == '') { |
|
159 die ("For security reasons, you must pass the remote ip to reCAPTCHA"); |
|
160 } |
|
161 |
|
162 |
|
163 |
|
164 //discard spam submissions |
|
165 if ($challenge == null || strlen($challenge) == 0 || $response == null || strlen($response) == 0) { |
|
166 $recaptcha_response = new ReCaptchaResponse(); |
|
167 $recaptcha_response->is_valid = false; |
|
168 $recaptcha_response->error = 'incorrect-captcha-sol'; |
|
169 return $recaptcha_response; |
|
170 } |
|
171 |
|
172 $response = _recaptcha_http_post (RECAPTCHA_VERIFY_SERVER, "/verify", |
|
173 array ( |
|
174 'privatekey' => $privkey, |
|
175 'remoteip' => $remoteip, |
|
176 'challenge' => $challenge, |
|
177 'response' => $response |
|
178 ) + $extra_params |
|
179 ); |
|
180 |
|
181 $answers = explode ("\n", $response [1]); |
|
182 $recaptcha_response = new ReCaptchaResponse(); |
|
183 |
|
184 if (trim ($answers [0]) == 'true') { |
|
185 $recaptcha_response->is_valid = true; |
|
186 } |
|
187 else { |
|
188 $recaptcha_response->is_valid = false; |
|
189 $recaptcha_response->error = $answers [1]; |
|
190 } |
|
191 return $recaptcha_response; |
|
192 |
|
193 } |
|
194 |
|
195 /** |
|
196 * gets a URL where the user can sign up for reCAPTCHA. If your application |
|
197 * has a configuration page where you enter a key, you should provide a link |
|
198 * using this function. |
|
199 * @param string $domain The domain where the page is hosted |
|
200 * @param string $appname The name of your application |
|
201 */ |
|
202 function recaptcha_get_signup_url ($domain = null, $appname = null) { |
|
203 return "http://recaptcha.net/api/getkey?" . _recaptcha_qsencode (array ('domain' => $domain, 'app' => $appname)); |
|
204 } |
|
205 |
|
206 function _recaptcha_aes_pad($val) { |
|
207 $block_size = 16; |
|
208 $numpad = $block_size - (strlen ($val) % $block_size); |
|
209 return str_pad($val, strlen ($val) + $numpad, chr($numpad)); |
|
210 } |
|
211 |
|
212 /* Mailhide related code */ |
|
213 |
|
214 function _recaptcha_aes_encrypt($val,$ky) { |
|
215 if (! function_exists ("mcrypt_encrypt")) { |
|
216 die ("To use reCAPTCHA Mailhide, you need to have the mcrypt php module installed."); |
|
217 } |
|
218 $mode=MCRYPT_MODE_CBC; |
|
219 $enc=MCRYPT_RIJNDAEL_128; |
|
220 $val=_recaptcha_aes_pad($val); |
|
221 return mcrypt_encrypt($enc, $ky, $val, $mode, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"); |
|
222 } |
|
223 |
|
224 |
|
225 function _recaptcha_mailhide_urlbase64 ($x) { |
|
226 return strtr(base64_encode ($x), '+/', '-_'); |
|
227 } |
|
228 |
|
229 /* gets the reCAPTCHA Mailhide url for a given email, public key and private key */ |
|
230 function recaptcha_mailhide_url($pubkey, $privkey, $email) { |
|
231 if ($pubkey == '' || $pubkey == null || $privkey == "" || $privkey == null) { |
|
232 die ("To use reCAPTCHA Mailhide, you have to sign up for a public and private key, " . |
|
233 "you can do so at <a href='http://mailhide.recaptcha.net/apikey'>http://mailhide.recaptcha.net/apikey</a>"); |
|
234 } |
|
235 |
|
236 |
|
237 $ky = pack('H*', $privkey); |
|
238 $cryptmail = _recaptcha_aes_encrypt ($email, $ky); |
|
239 |
|
240 return "http://mailhide.recaptcha.net/d?k=" . $pubkey . "&c=" . _recaptcha_mailhide_urlbase64 ($cryptmail); |
|
241 } |
|
242 |
|
243 /** |
|
244 * gets the parts of the email to expose to the user. |
|
245 * eg, given johndoe@example,com return ["john", "example.com"]. |
|
246 * the email is then displayed as john...@example.com |
|
247 */ |
|
248 function _recaptcha_mailhide_email_parts ($email) { |
|
249 $arr = preg_split("/@/", $email ); |
|
250 |
|
251 if (strlen ($arr[0]) <= 4) { |
|
252 $arr[0] = substr ($arr[0], 0, 1); |
|
253 } else if (strlen ($arr[0]) <= 6) { |
|
254 $arr[0] = substr ($arr[0], 0, 3); |
|
255 } else { |
|
256 $arr[0] = substr ($arr[0], 0, 4); |
|
257 } |
|
258 return $arr; |
|
259 } |
|
260 |
|
261 /** |
|
262 * Gets html to display an email address given a public an private key. |
|
263 * to get a key, go to: |
|
264 * |
|
265 * http://mailhide.recaptcha.net/apikey |
|
266 */ |
|
267 function recaptcha_mailhide_html($pubkey, $privkey, $email) { |
|
268 $emailparts = _recaptcha_mailhide_email_parts ($email); |
|
269 $url = recaptcha_mailhide_url ($pubkey, $privkey, $email); |
|
270 |
|
271 return htmlentities($emailparts[0]) . "<a href='" . htmlentities ($url) . |
|
272 "' 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]); |
|
273 |
|
274 } |
|
275 |
|
276 |
|
277 ?> |