| <?php | |
| /******************************************************************************* | |
| * Copyright (c) 2014 Eclipse Foundation and others. | |
| * All rights reserved. This program and the accompanying materials | |
| * are made available under the terms of the Eclipse Public License v1.0 | |
| * which accompanies this distribution, and is available at | |
| * http://eclipse.org/legal/epl-v10.html | |
| * | |
| * Contributors: | |
| * Christopher Guindon (Eclipse Foundation) - Initial implementation | |
| *******************************************************************************/ | |
| require_once ("recaptchaMailHide.class.php"); | |
| define("RECAPTCHA_API_SERVER", "www.google.com/recaptcha/api"); | |
| define("RECAPTCHA_VERIFY_SERVER", "www.google.com"); | |
| class ReCaptcha extends ReCaptchaMailHide { | |
| private $pubkey = ""; | |
| private $privkey = ""; | |
| private $challenge = NULL; | |
| private $response = NULL; | |
| private $use_ssl = TRUE; | |
| private $server = ""; | |
| private $remoteip = ""; | |
| private $is_valid = FALSE; | |
| private $error = ""; | |
| function __construct($ssl = TRUE) { | |
| parent::__construct(); | |
| $this->pubkey = RECAPTCHA_PUBKEY; | |
| $this->privkey = RECAPTCHA_PRIVKEY; | |
| if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { | |
| $ip = $_SERVER['HTTP_X_FORWARDED_FOR']; | |
| } | |
| else { | |
| $ip = $_SERVER['REMOTE_ADDR']; | |
| } | |
| $this->remoteip = $ip; | |
| $this->_use_ssl($ssl); | |
| } | |
| /** | |
| * Gets error from reCAPTCHA. | |
| * | |
| * @return string | |
| */ | |
| public function get_error() { | |
| return $this->error; | |
| } | |
| /** | |
| * Gets the challenge HTML (javascript and non-javascript version). | |
| * | |
| * This is called from the browser, and the resulting reCAPTCHA HTML widget | |
| * is embedded within the HTML form it was called from. | |
| * | |
| * @return string - The HTML to be embedded in the user's form. | |
| */ | |
| public function get_html() { | |
| if ($this->pubkey == NULL || $this->pubkey == '') { | |
| 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>"); | |
| } | |
| $errorpart = ""; | |
| if ($this->error) { | |
| $errorpart = "&error=" . $this->error; | |
| } | |
| return '<script type="text/javascript" src="'. $this->server . '/challenge?k=' . $this->pubkey . $errorpart . '"></script> | |
| <noscript> | |
| <iframe src="'. $this->server . '/noscript?k=' . $this->pubkey . $errorpart . '" height="300" width="500" frameborder="0"></iframe><br/> | |
| <textarea name="challenge_field" rows="3" cols="40"></textarea> | |
| <input type="hidden" name="response_field" value="manual_challenge"/> | |
| </noscript>'; | |
| } | |
| /** | |
| * Verify if the captcha anwser was correct. | |
| * | |
| * @return bool | |
| */ | |
| public function validate() { | |
| $this->verify_answer(); | |
| return $this->is_valid; | |
| } | |
| /** | |
| * Calls an HTTP POST function to verify if the user's guess was correct | |
| * | |
| * @param string $challenge | |
| * @param string $response | |
| * @param array $extra_params an array of extra variables to post to the server | |
| * | |
| * @return bool | |
| */ | |
| public function verify_answer($challenge = NULL, $response = NULL, $extra_params = array()) { | |
| if ($this->privkey == null || $this->privkey == '') { | |
| 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>"); | |
| } | |
| if ($this->remoteip == null || $this->remoteip == '') { | |
| die ("For security reasons, you must pass the remote ip to reCAPTCHA"); | |
| } | |
| //discard spam submissions | |
| if (!$this->_verify_spam($challenge, $response)) { | |
| $this->is_valid = FALSE; | |
| $this->error = 'incorrect-captcha-sol'; | |
| return FALSE; | |
| } | |
| $path = array_merge(array( | |
| 'privatekey' => $this->privkey, | |
| 'remoteip' => $this->remoteip, | |
| 'challenge' => $this->challenge, | |
| 'response' => $this->response | |
| ), $extra_params); | |
| $response = $this->_http_post(RECAPTCHA_VERIFY_SERVER, "/recaptcha/api/verify", $path); | |
| $answers = explode("\n", $response[0]); | |
| if (trim($answers[0]) == 'true') { | |
| $this->is_valid = TRUE; | |
| return TRUE; | |
| } | |
| else { | |
| $this->is_valid = FALSE; | |
| $this->error = $answers[1]; | |
| } | |
| return FALSE; | |
| } | |
| /** | |
| * Submits an HTTP POST to a reCAPTCHA server | |
| * | |
| * @param string $host | |
| * @param string $path | |
| * @param array $data | |
| * | |
| * @return array response | |
| */ | |
| private function _http_post($host, $path, $data) { | |
| $add_headers = array( | |
| "Host: $host", | |
| ); | |
| $cu = curl_init('https://' . $host . $path); | |
| curl_setopt($cu, CURLOPT_POST, TRUE); | |
| curl_setopt($cu, CURLOPT_RETURNTRANSFER, TRUE); | |
| curl_setopt($cu, CURLOPT_CONNECTTIMEOUT, 10); | |
| curl_setopt($cu, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); | |
| curl_setopt($cu, CURLOPT_USERAGENT, 'reCAPTCHA/PHP'); | |
| curl_setopt($cu, CURLOPT_POSTFIELDS, $data); | |
| curl_setopt($cu, CURLOPT_HEADER, FALSE); | |
| curl_setopt($cu, CURLOPT_HTTPHEADER, $add_headers); | |
| curl_setopt($cu, CURLOPT_CONNECTTIMEOUT, 30); | |
| curl_setopt($cu, CURLOPT_SSL_VERIFYPEER, 1); | |
| curl_setopt($cu, CURLOPT_SSL_VERIFYHOST, 2); | |
| // Need to use eclipse.org proxy | |
| curl_setopt($cu, CURLOPT_HTTPPROXYTUNNEL, TRUE); | |
| curl_setopt($cu, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); | |
| curl_setopt($cu, CURLOPT_PROXY, 'proxy.eclipse.org:9899'); | |
| $response = curl_exec($cu); | |
| if ($response === FALSE) { | |
| die('Error connecting to ' . $host . '.'); | |
| } | |
| $response = explode("\r\n\r\n", $response, 2); | |
| return $response; | |
| } | |
| /** | |
| * Encodes the given data into a query string format | |
| * | |
| * @param $data - array of string elements to be encoded | |
| * | |
| * @return string - encoded request | |
| */ | |
| private function _qsencode($data) { | |
| $req = ""; | |
| foreach ($data as $key => $value ) { | |
| $req .= $key . '=' . urlencode(stripslashes($value)) . '&'; | |
| } | |
| // Cut the last '&' | |
| $req = substr($req,0,strlen($req)-1); | |
| return $req; | |
| } | |
| /** | |
| * Verify if the request is spam before posting to reCAPTCHA. | |
| * | |
| * @param string $challenge | |
| * @param string $response | |
| * | |
| * @return boolean | |
| */ | |
| private function _verify_spam($challenge = NULL, $response = NULL) { | |
| $this->challenge = $challenge; | |
| $this->response = $response; | |
| if ((is_null($this->challenge) || empty($this->challenge)) && isset($_POST["recaptcha_response_field"])) { | |
| $this->challenge = $_POST["recaptcha_challenge_field"]; | |
| } | |
| if ((is_null($this->response) || empty($this->response)) && isset($_POST["recaptcha_response_field"])) { | |
| $this->response = $_POST["recaptcha_response_field"]; | |
| } | |
| if ($this->challenge == null || strlen($this->challenge) == 0 || $this->response == null || strlen($this->response) == 0) { | |
| return FALSE; | |
| } | |
| return TRUE; | |
| } | |
| /** | |
| * Set protocol for loading reCAPTCHA | |
| * | |
| * @param string $use_ssl | |
| * | |
| * @return boolean | |
| */ | |
| private function _use_ssl($use_ssl = TRUE) { | |
| $protocol = "http://"; | |
| if (is_bool($use_ssl)) { | |
| $this->use_ssl = $use_ssl; | |
| } | |
| if ($this->use_ssl) { | |
| $protocol = "https://"; | |
| } | |
| $this->server = $protocol . RECAPTCHA_API_SERVER; | |
| return $this->use_ssl; | |
| } | |
| } |