Révision be58a50c
Ajouté par Assos Assos il y a environ 7 ans
drupal7/sites/all/modules/recaptcha/recaptcha.module | ||
---|---|---|
2 | 2 |
|
3 | 3 |
/** |
4 | 4 |
* @file |
5 |
* Uses the reCAPTCHA web service to improve the CAPTCHA system.
|
|
5 |
* Verifies if user is a human without necessity to solve a CAPTCHA.
|
|
6 | 6 |
*/ |
7 | 7 |
|
8 |
require_once dirname(__FILE__) . '/recaptcha-php/src/ReCaptcha/ReCaptcha.php'; |
|
9 |
require_once dirname(__FILE__) . '/recaptcha-php/src/ReCaptcha/RequestMethod.php'; |
|
10 |
require_once dirname(__FILE__) . '/recaptcha-php/src/ReCaptcha/RequestParameters.php'; |
|
11 |
require_once dirname(__FILE__) . '/recaptcha-php/src/ReCaptcha/Response.php'; |
|
12 |
require_once dirname(__FILE__) . '/src/ReCaptcha/RequestMethod/Drupal7Post.php'; |
|
13 |
|
|
8 | 14 |
/** |
9 | 15 |
* Implements hook_help(). |
10 | 16 |
*/ |
11 | 17 |
function recaptcha_help($path, $arg) { |
12 |
$output = ''; |
|
13 |
|
|
14 | 18 |
switch ($path) { |
15 |
case 'admin/modules#name': |
|
16 |
$output .= t('reCAPTCHA'); |
|
17 |
break; |
|
18 |
|
|
19 |
case 'admin/modules#description': |
|
20 |
case 'admin/user/captcha/recaptcha': |
|
21 |
$output .= t('Uses the <a href="@url" target="_blank">reCAPTCHA</a> web service to improve the CAPTCHA system and protect email addresses.', array('@url' => url('https://www.google.com/recaptcha'))); |
|
22 |
break; |
|
23 |
|
|
24 |
case 'admin/help#recaptcha': |
|
25 |
$output .= '<p>' . |
|
26 |
t('Uses the reCAPTCHA web service to improve the CAPTCHA module and protect email addresses. For more information on what reCAPTCHA is, visit <a href="@url" target="_blank">the official website</a>.', array('@url' => url('https://www.google.com/recaptcha'))) . |
|
27 |
'</p><h3>' . |
|
28 |
t('Configuration') . |
|
29 |
'</h3><p>' . |
|
30 |
t('The settings associated with reCAPTCHA can be found in the <a href="@recaptchatab">reCAPTCHA tab</a>, in the <a href="@captchasettings">CAPTCHA settings</a>. You must set your public and private reCAPTCHA keys in order to use the module. Once the public and private keys are set, visit the <a href="@captchasettings">CAPTCHA settings</a>, where you can choose where reCAPTCHA should be displayed.', array('@recaptchatab' => url('admin/user/captcha/recaptcha'), '@captchasettings' => url('admin/user/captcha'))) . |
|
31 |
'</p>'; |
|
32 |
break; |
|
19 |
case 'admin/config/people/captcha/recaptcha': |
|
20 |
return t('Google <a href="@url">reCAPTCHA</a> is a free service to protect your website from spam and abuse. reCAPTCHA uses an advanced risk analysis engine and adaptive CAPTCHAs to keep automated software from engaging in abusive activities on your site. It does this while letting your valid users pass through with ease.', array('@url' => 'https://www.google.com/recaptcha')); |
|
33 | 21 |
} |
22 |
} |
|
34 | 23 |
|
35 |
return $output; |
|
24 |
/** |
|
25 |
* Implements hook_theme(). |
|
26 |
*/ |
|
27 |
function recaptcha_theme() { |
|
28 |
return array( |
|
29 |
'recaptcha_widget_noscript' => array( |
|
30 |
'variables' => array( |
|
31 |
'widget' => NULL, |
|
32 |
), |
|
33 |
'template' => 'recaptcha-widget-noscript', |
|
34 |
), |
|
35 |
); |
|
36 | 36 |
} |
37 | 37 |
|
38 | 38 |
/** |
39 | 39 |
* Implements hook_menu(). |
40 | 40 |
*/ |
41 | 41 |
function recaptcha_menu() { |
42 |
$items = array(); |
|
43 | 42 |
$items['admin/config/people/captcha/recaptcha'] = array( |
44 | 43 |
'title' => 'reCAPTCHA', |
45 |
'description' => 'Administer the reCAPTCHA web service.', |
|
44 |
'description' => 'Administer the Google No CAPTCHA reCAPTCHA web service.',
|
|
46 | 45 |
'page callback' => 'drupal_get_form', |
47 | 46 |
'page arguments' => array('recaptcha_admin_settings'), |
48 | 47 |
'access arguments' => array('administer recaptcha'), |
49 | 48 |
'type' => MENU_LOCAL_TASK, |
50 | 49 |
'file' => 'recaptcha.admin.inc', |
50 |
'weight' => 1, |
|
51 | 51 |
); |
52 |
|
|
52 | 53 |
return $items; |
53 | 54 |
} |
54 | 55 |
|
... | ... | |
58 | 59 |
function recaptcha_permission() { |
59 | 60 |
return array( |
60 | 61 |
'administer recaptcha' => array( |
61 |
'title' => t('reCaptcha Administration'),
|
|
62 |
'description' => t('Administer reCaptcha settings'),
|
|
62 |
'title' => t('Administer reCAPTCHA'),
|
|
63 |
'description' => t('Administer reCAPTCHA settings'),
|
|
63 | 64 |
), |
64 | 65 |
); |
65 | 66 |
} |
... | ... | |
68 | 69 |
* Implements hook_captcha(). |
69 | 70 |
*/ |
70 | 71 |
function recaptcha_captcha($op, $captcha_type = '') { |
72 |
global $language; |
|
73 |
|
|
71 | 74 |
switch ($op) { |
72 | 75 |
case 'list': |
73 | 76 |
return array('reCAPTCHA'); |
... | ... | |
75 | 78 |
case 'generate': |
76 | 79 |
$captcha = array(); |
77 | 80 |
if ($captcha_type == 'reCAPTCHA') { |
78 |
// Retrieve configuration variables. |
|
79 |
$recaptcha_theme = variable_get('recaptcha_theme', 'red'); |
|
80 |
$recaptcha_tabindex = variable_get('recaptcha_tabindex', NULL); |
|
81 |
$recaptcha_public_key = variable_get('recaptcha_public_key', FALSE); |
|
82 |
$recaptcha_ajax_api = variable_get('recaptcha_ajax_api', FALSE); |
|
83 |
|
|
84 |
// Test if reCAPTCHA can be used, falling back to Math if it is not |
|
85 |
// configured, the library won't load, or the server is down. |
|
86 |
if (!$recaptcha_public_key || !_recaptcha_load_library() || !_recaptcha_server_is_up()) { |
|
87 |
return captcha_captcha('generate', 'Math'); |
|
88 |
} |
|
89 |
|
|
90 |
if ($recaptcha_ajax_api) { |
|
91 |
// By default CAPTCHA turns off page caching on any page where a |
|
92 |
// CAPTCHA challenge appears. If recaptcha is using AJAX API, set |
|
93 |
// caching back to its old state as stored in DB. |
|
94 |
global $conf; |
|
95 |
$conf['cache'] = unserialize(db_query("SELECT value FROM {variable} WHERE name = 'cache'")->fetchField()); |
|
96 |
} |
|
97 |
|
|
98 |
$recaptcha_options = array( |
|
99 |
'theme' => $recaptcha_theme, |
|
100 |
); |
|
101 |
|
|
102 |
// Localization support. |
|
103 |
global $language; |
|
104 |
if (isset($language->language)) { |
|
105 |
// reCAPTCHA uses two-character language codes, so 'pt-br' must be |
|
106 |
// passed as 'pt'. |
|
107 |
$recaptcha_options['lang'] = drupal_substr($language->language, 0, 2); |
|
108 |
} |
|
109 |
|
|
110 |
// Construct the Javascript, but only display it once. |
|
111 |
static $_recaptcha_jsadded = FALSE; |
|
112 |
if ($_recaptcha_jsadded == FALSE && $recaptcha_ajax_api == FALSE) { |
|
113 |
$_recaptcha_jsadded = TRUE; |
|
114 |
|
|
115 |
// Add support to display the custom theme. |
|
116 |
if ($recaptcha_theme == 'custom') { |
|
117 |
$recaptcha_options['custom_theme_widget'] = 'recaptcha_custom_theme_widget'; |
|
118 |
} |
|
81 |
$recaptcha_site_key = variable_get('recaptcha_site_key', ''); |
|
82 |
$recaptcha_secret_key = variable_get('recaptcha_secret_key', ''); |
|
83 |
|
|
84 |
if (!empty($recaptcha_site_key) && !empty($recaptcha_secret_key)) { |
|
85 |
// Build the reCAPTCHA captcha form if site_key and secret_key are |
|
86 |
// configured. Captcha requires TRUE to be returned in solution. |
|
87 |
$captcha['solution'] = TRUE; |
|
88 |
$captcha['captcha_validate'] = 'recaptcha_captcha_validation'; |
|
89 |
$captcha['form']['captcha_response'] = array( |
|
90 |
'#type' => 'hidden', |
|
91 |
'#value' => 'Google no captcha', |
|
92 |
); |
|
119 | 93 |
|
120 |
// Set the default tab index. |
|
121 |
if (!empty($recaptcha_tabindex)) { |
|
122 |
$recaptcha_options['tabindex'] = $recaptcha_tabindex; |
|
94 |
$noscript = ''; |
|
95 |
if (variable_get('recaptcha_noscript', 0)) { |
|
96 |
$variables = array( |
|
97 |
'sitekey' => $recaptcha_site_key, |
|
98 |
'language' => $language->language, |
|
99 |
); |
|
100 |
$noscript = theme('recaptcha_widget_noscript', array('widget' => $variables)); |
|
123 | 101 |
} |
124 |
drupal_add_js('var RecaptchaOptions = ' . drupal_json_encode($recaptcha_options) . ';', array('type' => 'inline')); |
|
125 |
} |
|
126 | 102 |
|
127 |
// Create the form. Captcha requires TRUE to be returned in solution. |
|
128 |
$captcha['solution'] = TRUE; |
|
129 |
$captcha['captcha_validate'] = 'recaptcha_captcha_validation'; |
|
130 |
|
|
131 |
// If 'Disable Client-Side Cookies' is set, then add query string to |
|
132 |
// end of the public key string before passing to recaptchalib. |
|
133 |
if (variable_get('recaptcha_nocookies', FALSE)) { |
|
134 |
$recaptcha_public_key .= '&nocookie=1'; |
|
135 |
} |
|
103 |
$attributes = array( |
|
104 |
'class' => 'g-recaptcha', |
|
105 |
'data-sitekey' => $recaptcha_site_key, |
|
106 |
'data-theme' => variable_get('recaptcha_theme', 'light'), |
|
107 |
'data-type' => variable_get('recaptcha_type', 'image'), |
|
108 |
'data-size' => variable_get('recaptcha_size', ''), |
|
109 |
'data-tabindex' => variable_get('recaptcha_tabindex', 0), |
|
110 |
); |
|
111 |
// Filter out empty tabindex/size. |
|
112 |
$attributes = array_filter($attributes); |
|
136 | 113 |
|
137 |
$captcha['form']['captcha_response'] = array(
|
|
138 |
'#type' => 'hidden',
|
|
139 |
'#value' => 'reCAPTCHA',
|
|
140 |
); |
|
114 |
$captcha['form']['recaptcha_widget'] = array(
|
|
115 |
'#markup' => '<div' . drupal_attributes($attributes) . '></div>',
|
|
116 |
'#suffix' => $noscript,
|
|
117 |
);
|
|
141 | 118 |
|
142 |
// Expose the form, either straight HTML, or using the AJAX API. |
|
143 |
// Build the custom theme HTML if necessary. |
|
144 |
$recaptcha_custom_html = ($recaptcha_theme == 'custom') ? theme('recaptcha_custom_widget') : ''; |
|
145 |
if ($recaptcha_ajax_api == FALSE) { |
|
146 |
// Only generate recaptcha_get_html() if we're not using the AJAX API. |
|
147 |
$html = recaptcha_get_html($recaptcha_public_key, NULL, TRUE); |
|
148 |
$captcha['form']['captcha_form'] = array( |
|
149 |
'#type' => 'item', |
|
150 |
'#markup' => (!empty($recaptcha_custom_html) ? '<div id="recaptcha_custom_theme_widget">' . $recaptcha_custom_html . '</div>' : '') . $html, |
|
119 |
// @todo: #1664602: D7 does not yet support "async" in drupal_add_js(). |
|
120 |
// drupal_add_js(url('https://www.google.com/recaptcha/api.js', array('query' => array('hl' => $language->language), 'absolute' => TRUE)), array('defer' => TRUE, 'async' => TRUE, 'type' => 'external')); |
|
121 |
$data = array( |
|
122 |
'#tag' => 'script', |
|
123 |
'#value' => '', |
|
124 |
'#attributes' => array( |
|
125 |
'src' => url('https://www.google.com/recaptcha/api.js', array('query' => array('hl' => $language->language), 'absolute' => TRUE)), |
|
126 |
'async' => 'async', |
|
127 |
'defer' => 'defer', |
|
128 |
), |
|
151 | 129 |
); |
130 |
drupal_add_html_head($data, 'recaptcha_api'); |
|
152 | 131 |
} |
153 | 132 |
else { |
154 |
$captcha['form']['captcha_form'] = array( |
|
155 |
'#type' => 'item', |
|
156 |
// Create the destination container, inserting any custom theme HTML |
|
157 |
// necessary ($recaptcha_custom_html will be empty if we are not |
|
158 |
// using custom theme). |
|
159 |
'#markup' => '<div id="recaptcha_ajax_api_container">' . $recaptcha_custom_html . '</div>', |
|
160 |
); |
|
161 |
drupal_add_js('https://www.google.com/recaptcha/api/js/recaptcha_ajax.js', array('type' => 'external')); |
|
162 |
$recaptcha_options['public_key'] = $recaptcha_public_key; |
|
163 |
$recaptcha_options['container'] = 'recaptcha_ajax_api_container'; |
|
164 |
drupal_add_js(array('recaptcha' => $recaptcha_options), 'setting'); |
|
165 |
drupal_add_js(drupal_get_path('module', 'recaptcha') . '/recaptcha.js'); |
|
133 |
// Fallback to Math captcha as reCAPTCHA is not configured. |
|
134 |
$captcha = captcha_captcha('generate', 'Math'); |
|
166 | 135 |
} |
167 | 136 |
} |
168 | 137 |
return $captcha; |
... | ... | |
170 | 139 |
} |
171 | 140 |
|
172 | 141 |
/** |
173 |
* Test whether the reCAPTCHA server is up. |
|
174 |
* |
|
175 |
* @return bool |
|
176 |
* TRUE if the reCAPTCHA server is up, FALSE otherwise. |
|
142 |
* CAPTCHA Callback; Validates the reCAPTCHA code. |
|
177 | 143 |
*/ |
178 |
function _recaptcha_test_recaptcha_server() { |
|
179 |
$response = drupal_http_request('https://' . RECAPTCHA_VERIFY_SERVER); |
|
180 |
if (empty($response->error)) { |
|
181 |
return TRUE; |
|
182 |
} |
|
183 |
else { |
|
184 |
watchdog('reCAPTCHA', 'Unable to connect with the reCAPTCHA server (@server): @errno: @errstr', array( |
|
185 |
'@server' => RECAPTCHA_VERIFY_SERVER, |
|
186 |
'@errno' => $response->code, |
|
187 |
'@errstr' => $response->error, |
|
188 |
), WATCHDOG_ERROR); |
|
144 |
function recaptcha_captcha_validation($solution, $response, $element, $form_state) { |
|
145 |
$recaptcha_secret_key = variable_get('recaptcha_secret_key', ''); |
|
146 |
if (empty($_POST['g-recaptcha-response']) || empty($recaptcha_secret_key)) { |
|
189 | 147 |
return FALSE; |
190 | 148 |
} |
191 |
} |
|
192 | 149 |
|
193 |
/** |
|
194 |
* Return the cached output of _recaptcha_test_recaptcha_server(). |
|
195 |
* |
|
196 |
* @return bool |
|
197 |
* TRUE if the reCAPTCHA server was up last time it was checked, FALSE |
|
198 |
* otherwise. |
|
199 |
*/ |
|
200 |
function _recaptcha_server_is_up() { |
|
201 |
static $server_status; |
|
202 |
// Use static cache value, if available. |
|
203 |
if (isset($server_status)) { |
|
204 |
return $server_status; |
|
205 |
} |
|
206 |
// Check if the status is cached already. |
|
207 |
$status_cache = cache_get('recaptcha_server_status'); |
|
208 |
if ($status_cache !== FALSE) { |
|
209 |
$server_status = (bool) $status_cache; |
|
210 |
return $server_status; |
|
211 |
} |
|
212 |
// Status is not cached. Check if server is up. |
|
213 |
$server_status = _recaptcha_test_recaptcha_server(); |
|
150 |
// Use drupal_http_request() to circumvent all issues with the Google library. |
|
151 |
$recaptcha = new \ReCaptcha\ReCaptcha($recaptcha_secret_key, new \ReCaptcha\RequestMethod\Drupal7Post()); |
|
214 | 152 |
|
215 |
// Set to 5 minutes, if interval is not set. |
|
216 |
$cache_period = variable_get('recaptcha_server_status_check_interval', 5); |
|
217 |
// Save it as integer as cache_get returns FALSE, if not found. |
|
218 |
cache_set('recaptcha_server_status', (int) $server_status, 'cache', time() + ($cache_period * 60)); |
|
219 |
return $server_status; |
|
220 |
} |
|
153 |
$resp = $recaptcha->verify( |
|
154 |
$_POST['g-recaptcha-response'], |
|
155 |
ip_address() |
|
156 |
); |
|
221 | 157 |
|
222 |
/**
|
|
223 |
* CAPTCHA Callback; Validates the reCAPTCHA code.
|
|
224 |
*/
|
|
225 |
function recaptcha_captcha_validation($solution = NULL, $response = NULL) {
|
|
226 |
global $user;
|
|
227 |
$recaptcha_private_key = variable_get('recaptcha_private_key', FALSE);
|
|
228 |
$ip_address = ip_address();
|
|
229 |
if ($recaptcha_private_key && $ip_address && $response === 'reCAPTCHA' && !empty($_POST['recaptcha_challenge_field']) && !empty($_POST['recaptcha_response_field']) && _recaptcha_server_is_up()) {
|
|
230 |
$resp = recaptcha_check_answer(
|
|
231 |
$recaptcha_private_key,
|
|
232 |
$ip_address,
|
|
233 |
check_plain($_POST['recaptcha_challenge_field']),
|
|
234 |
check_plain($_POST['recaptcha_response_field'])
|
|
158 |
if ($resp->isSuccess()) {
|
|
159 |
// Verified!
|
|
160 |
return TRUE;
|
|
161 |
}
|
|
162 |
else {
|
|
163 |
// Error code reference, https://developers.google.com/recaptcha/docs/verify
|
|
164 |
$error_codes = array(
|
|
165 |
'missing-input-secret' => t('The secret parameter is missing.'),
|
|
166 |
'invalid-input-secret' => t('The secret parameter is invalid or malformed.'),
|
|
167 |
'missing-input-response' => t('The response parameter is missing.'),
|
|
168 |
'invalid-input-response' => t('The response parameter is invalid or malformed.'),
|
|
169 |
'invalid-json' => t('The json response is invalid or malformed.'),
|
|
170 |
'unknown' => t('Unknown error.'),
|
|
235 | 171 |
); |
236 |
return $resp->is_valid; |
|
172 |
foreach ($resp->getErrorCodes() as $code) { |
|
173 |
if (!isset($error_codes[$code])) { |
|
174 |
$code = 'unknown'; |
|
175 |
} |
|
176 |
watchdog('reCAPTCHA web service', '@error', array('@error' => $error_codes[$code]), WATCHDOG_ERROR); |
|
177 |
} |
|
237 | 178 |
} |
238 | 179 |
return FALSE; |
239 | 180 |
} |
240 | 181 |
|
241 | 182 |
/** |
242 |
* Implements hook_theme(). |
|
243 |
*/ |
|
244 |
function recaptcha_theme() { |
|
245 |
return array( |
|
246 |
'recaptcha_custom_widget' => array( |
|
247 |
'arguments' => array(), |
|
248 |
), |
|
249 |
); |
|
250 |
} |
|
251 |
|
|
252 |
/** |
|
253 |
* Theme function: creates the custom themed recaptcha widget. |
|
183 |
* Process variables for recaptcha-widget-noscript.tpl.php. |
|
254 | 184 |
* |
255 |
* @ingroup themeable |
|
256 |
*/ |
|
257 |
function theme_recaptcha_custom_widget() { |
|
258 |
$recaptcha_only_if_incorrect_sol = t('Incorrect please try again'); |
|
259 |
$recaptcha_only_if_image_enter = t('Enter the words above:'); |
|
260 |
$recaptcha_only_if_audio_enter = t('Enter the words you hear:'); |
|
261 |
$recaptcha_get_another_captcha = t('Get another CAPTCHA'); |
|
262 |
$recaptcha_only_if_image = t('Get an audio CAPTCHA'); |
|
263 |
$recaptcha_only_if_audio = t('Get an image CAPTCHA'); |
|
264 |
$help = t('Help'); |
|
265 |
return <<<EOT |
|
266 |
<div id="recaptcha_image"></div> |
|
267 |
<div class="recaptcha_only_if_incorrect_sol" style="color:red">$recaptcha_only_if_incorrect_sol</div> |
|
268 |
<span class="recaptcha_only_if_image">$recaptcha_only_if_image_enter</span> |
|
269 |
<span class="recaptcha_only_if_audio">$recaptcha_only_if_audio_enter</span> |
|
270 |
<input type="text" id="recaptcha_response_field" name="recaptcha_response_field" /> |
|
271 |
<div class="recaptcha_get_another_captcha"><a href="javascript:Recaptcha.reload()">$recaptcha_get_another_captcha</a></div> |
|
272 |
<div class="recaptcha_only_if_image"><a href="javascript:Recaptcha.switch_type('audio')">$recaptcha_only_if_image</a></div> |
|
273 |
<div class="recaptcha_only_if_audio"><a href="javascript:Recaptcha.switch_type('image')">$recaptcha_only_if_audio</a></div> |
|
274 |
<div class="recaptcha_help"><a href="javascript:Recaptcha.showhelp()">$help</a></div> |
|
275 |
EOT; |
|
276 |
} |
|
277 |
|
|
278 |
/** |
|
279 |
* Load the recaptcha library. |
|
185 |
* @see recaptcha-widget-noscript.tpl.php |
|
280 | 186 |
*/ |
281 |
function _recaptcha_load_library() { |
|
282 |
return module_load_include('php', 'recaptcha', 'recaptcha-php-1.11/recaptchalib'); |
|
187 |
function template_preprocess_recaptcha_widget_noscript(&$variables) { |
|
188 |
$variables['sitekey'] = check_plain($variables['widget']['sitekey']); |
|
189 |
$variables['language'] = check_plain($variables['widget']['language']); |
|
190 |
$variables['url'] = check_url(url('https://www.google.com/recaptcha/api/fallback', array('query' => array('k' => $variables['widget']['sitekey'], 'hl' => $variables['widget']['language']), 'absolute' => TRUE))); |
|
283 | 191 |
} |
Formats disponibles : Unified diff
Weekly update of contrib modules