diff --git a/library/includes/classes/recaptcha.php b/library/includes/classes/recaptcha.php
index bdc7580ff..43dbbd6e8 100644
--- a/library/includes/classes/recaptcha.php
+++ b/library/includes/classes/recaptcha.php
@@ -1,132 +1,146 @@
getMessage();
+ }
+}
+
+class Client
{
- private static $_signupUrl = "https://www.google.com/recaptcha/admin";
- private static $_siteVerifyUrl = "https://www.google.com/recaptcha/api/siteverify?";
private $_secret;
- private static $_version = "php_1.0";
+ private $_curl_opts;
/**
- * Constructor.
+ * Constructor
*
- * @param string $secret shared secret between site and ReCAPTCHA server.
+ * @param string $secret shared secret between site and ReCAPTCHA server
+ * @param array $curl_opts array of curl parameters
+ *
+ * @throws Exception
*/
- function ReCaptcha($secret)
+ public function __construct($secret, array $curl_opts = array())
{
- if ($secret == null || $secret == "") {
- die("To use Google reCAPTCHA you must get an API key from " . self::$_signupUrl . "");
+ if (is_null($secret) || $secret == '') {
+ throw new Exception('To use reCAPTCHA you must get an API key from ' . SIGNUP_URL . '');
}
$this->_secret = $secret;
+ if (!empty($curl_opts)) {
+ $this->_curl_opts = $curl_opts;
+ }
}
/**
- * Encodes the given data into a query string format.
+ * Encodes the given data into a query string format
*
- * @param array $data array of string elements to be encoded.
+ * @param array $data array of string elements to be encoded
*
- * @return string - encoded request.
+ * @return string - encoded request
*/
private function _encodeQS($data)
{
- $req = "";
+ $req = array();
foreach ($data as $key => $value) {
- $req .= $key . '=' . urlencode(stripslashes($value)) . '&';
+ $req[] = $key . '=' . urlencode(stripslashes(trim($value)));
}
-
- // Cut the last '&'
- $req = substr($req, 0, strlen($req) - 1);
- return $req;
+ return implode('&', $req);
}
/**
- * Submits an HTTP GET to a reCAPTCHA server.
+ * Submits an HTTP GET to a reCAPTCHA server
*
- * @param string $path url path to recaptcha server.
- * @param array $data array of parameters to be sent.
+ * @param string $path url path to reCAPTCHA server
+ * @param array $data array of parameters to be sent
*
+ * @throws Exception
* @return array response
*/
private function _submitHTTPGet($path, $data)
{
$req = $this->_encodeQS($data);
- $response = file_get_contents($path . $req);
+ // Prefer curl
+ if (function_exists('curl_version')) {
+ $opts = array(
+ CURLOPT_HEADER => false,
+ CURLOPT_RETURNTRANSFER => true,
+ CURLOPT_FOLLOWLOCATION => true,
+ CURLOPT_USERAGENT => 'ReCaptcha ' . VERSION,
+ CURLOPT_AUTOREFERER => true,
+ CURLOPT_CONNECTTIMEOUT => 60,
+ CURLOPT_TIMEOUT => 60,
+ CURLOPT_MAXREDIRS => 5,
+ CURLOPT_ENCODING => '',
+ );
+ // Check if we got overrides, or extra options (eg. proxy configuration)
+ if (is_array($this->_curl_opts) && !empty($this->_curl_opts)) {
+ $opts = array_merge($opts, $this->_curl_opts);
+ }
+ $conn = curl_init($path . $req);
+ curl_setopt_array($conn, $opts);
+ $response = curl_exec($conn);
+ // Handle a connection error
+ $errno = curl_errno($conn);
+ if ($errno !== 0) {
+ throw new Exception('Fatal error while contacting reCAPTCHA. ' . $errno . ': ' . curl_error($conn));
+ }
+ curl_close($conn);
+ } else {
+ $response = file_get_contents($path . $req);
+ }
return $response;
}
/**
- * Calls the reCAPTCHA siteverify API to verify whether the user passes
- * CAPTCHA test.
+ * Calls the reCAPTCHA siteverify API to verify whether the user passes test
*
- * @param string $remoteIp IP address of end user.
- * @param string $response response string from recaptcha verification.
+ * @param string $remoteIp IP address of end user
+ * @param string $response response string from reCAPTCHA verification
*
- * @return ReCaptchaResponse
+ * @return ReCaptcha\Response
*/
public function verifyResponse($remoteIp, $response)
{
// Discard empty solution submissions
- if ($response == null || strlen($response) == 0) {
- $recaptchaResponse = new ReCaptchaResponse();
+ if (is_null($response) || strlen($response) == 0) {
+ $recaptchaResponse = new Response();
$recaptchaResponse->success = false;
$recaptchaResponse->errorCodes = 'missing-input';
return $recaptchaResponse;
}
+ // Send request
$getResponse = $this->_submitHttpGet(
- self::$_siteVerifyUrl,
+ VERIFY_URL,
array(
'secret' => $this->_secret,
'remoteip' => $remoteIp,
- 'v' => self::$_version,
+ 'v' => VERSION,
'response' => $response
)
);
$answers = json_decode($getResponse, true);
- $recaptchaResponse = new ReCaptchaResponse();
+ $recaptchaResponse = new Response();
+ // Parse answer
if (trim($answers['success']) == true) {
$recaptchaResponse->success = true;
} else {
diff --git a/library/includes/functions.php b/library/includes/functions.php
index 5c3b186f9..7898478de 100644
--- a/library/includes/functions.php
+++ b/library/includes/functions.php
@@ -2664,14 +2664,14 @@ function bb_captcha ($mode, $callback = '')
{
global $bb_cfg, $userdata;
- require_once(CLASS_DIR .'recaptcha.php');
+ require_once(CLASS_DIR . 'recaptcha.php');
$secret = $bb_cfg['captcha']['secret_key'];
$public = $bb_cfg['captcha']['public_key'];
$theme = $bb_cfg['captcha']['theme'];
$lang = $bb_cfg['lang'][$userdata['user_lang']]['captcha'];
- $reCaptcha = new ReCaptcha($secret);
+ $reCaptcha = new Google\ReCaptcha\Client($secret);
switch ($mode)
{
@@ -2692,12 +2692,15 @@ function bb_captcha ($mode, $callback = '')
case 'check':
$resp = null;
- $error = null;
$g_resp = request_var('g-recaptcha-response', '');
if ($g_resp) {
- $resp = $reCaptcha->verifyResponse($_SERVER["REMOTE_ADDR"], $g_resp);
+ try {
+ $resp = $reCaptcha->verifyResponse($_SERVER["REMOTE_ADDR"], $g_resp);
+ } catch (ReCaptchaException $e) {
+ $e->getError();
+ }
}
- if ($resp != null && $resp->success) {
+ if (is_object($resp) && $resp->success === true) {
return true;
} else {
return false;
@@ -2705,7 +2708,7 @@ function bb_captcha ($mode, $callback = '')
break;
default:
- bb_simple_die(__FUNCTION__ .": invalid mode '$mode'");
+ bb_simple_die(__FUNCTION__ . ": invalid mode '$mode'");
}
return false;
}
\ No newline at end of file
diff --git a/library/includes/init_bb.php b/library/includes/init_bb.php
index 8ba6bf91e..59d0b781b 100644
--- a/library/includes/init_bb.php
+++ b/library/includes/init_bb.php
@@ -1,7 +1,7 @@