1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
use EventEspresso\core\exceptions\InvalidDataTypeException; |
4
|
|
|
use EventEspresso\core\exceptions\InvalidInterfaceException; |
5
|
|
|
use ReCaptcha\ReCaptcha; |
6
|
|
|
use ReCaptcha\RequestMethod\SocketPost; |
7
|
|
|
use ReCaptcha\Response; |
8
|
|
|
|
9
|
|
|
defined('EVENT_ESPRESSO_VERSION') || exit('NO direct script access allowed'); |
10
|
|
|
|
11
|
|
|
|
12
|
|
|
|
13
|
|
|
/** |
14
|
|
|
* EED_Recaptcha |
15
|
|
|
* PLZ NOTE: ALL ADMIN SETTINGS FUNCTIONALITY HAS BEEN MOVED TO |
16
|
|
|
* \EventEspresso\caffeinated\modules\recaptcha_invisible\RecaptchaAdminSettings |
17
|
|
|
* |
18
|
|
|
* @package Event Espresso |
19
|
|
|
* @subpackage /modules/recaptcha/ |
20
|
|
|
* @author Brent Christensen |
21
|
|
|
*/ |
22
|
|
|
class EED_Recaptcha extends EED_Module |
23
|
|
|
{ |
24
|
|
|
|
25
|
|
|
/** |
26
|
|
|
* @var EE_Registration_Config $config |
27
|
|
|
*/ |
28
|
|
|
private static $config; |
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* @type bool $_not_a_robot |
32
|
|
|
*/ |
33
|
|
|
private static $_not_a_robot; |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* @type string $_recaptcha_response |
37
|
|
|
*/ |
38
|
|
|
private static $_recaptcha_response; |
39
|
|
|
|
40
|
|
|
|
41
|
|
|
/** |
42
|
|
|
* @return EED_Module|EED_Recaptcha |
43
|
|
|
*/ |
44
|
|
|
public static function instance() |
45
|
|
|
{ |
46
|
|
|
return parent::get_instance(__CLASS__); |
47
|
|
|
} |
48
|
|
|
|
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* set_hooks - for hooking into EE Core, other modules, etc |
52
|
|
|
* |
53
|
|
|
* @return void |
54
|
|
|
* @throws InvalidArgumentException |
55
|
|
|
* @throws InvalidInterfaceException |
56
|
|
|
* @throws InvalidDataTypeException |
57
|
|
|
*/ |
58
|
|
|
public static function set_hooks() |
59
|
|
|
{ |
60
|
|
|
EED_Recaptcha::$config = EE_Registry::instance()->CFG->registration; |
61
|
|
|
// use_captcha ? |
62
|
|
|
if ( |
63
|
|
|
EED_Recaptcha::useRecaptcha() |
64
|
|
|
&& EED_Recaptcha::notPaymentOptionsRevisit() |
65
|
|
|
) { |
66
|
|
|
EED_Recaptcha::set_definitions(); |
67
|
|
|
EED_Recaptcha::enqueue_styles_and_scripts(); |
68
|
|
|
add_action('wp', array('EED_Recaptcha', 'set_late_hooks'), 1, 0); |
69
|
|
|
add_action( |
70
|
|
|
'AHEE__before_spco_whats_next_buttons', |
71
|
|
|
array('EED_Recaptcha', 'display_recaptcha'), 10, 0 |
72
|
|
|
); |
73
|
|
|
add_filter( |
74
|
|
|
'FHEE__EED_Single_Page_Checkout__init___continue_reg', |
75
|
|
|
array('EED_Recaptcha', 'not_a_robot') |
76
|
|
|
); |
77
|
|
|
add_filter( |
78
|
|
|
'FHEE__EE_SPCO_Reg_Step__set_completed___completed', |
79
|
|
|
array('EED_Recaptcha', 'not_a_robot') |
80
|
|
|
); |
81
|
|
|
add_filter( |
82
|
|
|
'FHEE__EE_SPCO_JSON_Response___toString__JSON_response', |
83
|
|
|
array('EED_Recaptcha', 'recaptcha_response') |
84
|
|
|
); |
85
|
|
|
add_filter( |
86
|
|
|
'FHEE__EED_Recaptcha___bypass_recaptcha__bypass_request_params_array', |
87
|
|
|
array('EED_Recaptcha', 'bypass_recaptcha_for_spco_load_payment_method') |
88
|
|
|
); |
89
|
|
|
} |
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
|
93
|
|
|
/** |
94
|
|
|
* set_hooks_admin - for hooking into EE Admin Core, other modules, etc |
95
|
|
|
* |
96
|
|
|
* @return void |
97
|
|
|
* @throws InvalidArgumentException |
98
|
|
|
* @throws InvalidInterfaceException |
99
|
|
|
* @throws InvalidDataTypeException |
100
|
|
|
*/ |
101
|
|
|
public static function set_hooks_admin() |
102
|
|
|
{ |
103
|
|
|
EED_Recaptcha::$config = EE_Registry::instance()->CFG->registration; |
104
|
|
|
EED_Recaptcha::set_definitions(); |
105
|
|
|
// use_captcha ? |
106
|
|
|
if ( |
107
|
|
|
EED_Recaptcha::useRecaptcha() |
108
|
|
|
&& EED_Recaptcha::notPaymentOptionsRevisit() |
109
|
|
|
&& EE_Registry::instance()->REQ->get('step', '') !== '' |
110
|
|
|
) { |
111
|
|
|
EED_Recaptcha::enqueue_styles_and_scripts(); |
112
|
|
|
add_filter( |
113
|
|
|
'FHEE__EED_Single_Page_Checkout__init___continue_reg', |
114
|
|
|
array('EED_Recaptcha', 'not_a_robot') |
115
|
|
|
); |
116
|
|
|
add_filter( |
117
|
|
|
'FHEE__EE_SPCO_Reg_Step__set_completed___completed', |
118
|
|
|
array('EED_Recaptcha', 'not_a_robot') |
119
|
|
|
); |
120
|
|
|
add_filter( |
121
|
|
|
'FHEE__EE_SPCO_JSON_Response___toString__JSON_response', |
122
|
|
|
array('EED_Recaptcha', 'recaptcha_response') |
123
|
|
|
); |
124
|
|
|
} |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
|
128
|
|
|
/** |
129
|
|
|
* @return void |
130
|
|
|
*/ |
131
|
|
|
public static function set_definitions() |
132
|
|
|
{ |
133
|
|
|
if (is_user_logged_in()) { |
134
|
|
|
EED_Recaptcha::$_not_a_robot = true; |
135
|
|
|
} |
136
|
|
|
define( |
137
|
|
|
'RECAPTCHA_BASE_PATH', |
138
|
|
|
rtrim(str_replace(array('\\', '/'), DS, plugin_dir_path(__FILE__)), DS) . DS |
139
|
|
|
); |
140
|
|
|
define('RECAPTCHA_BASE_URL', plugin_dir_url(__FILE__)); |
141
|
|
|
} |
142
|
|
|
|
143
|
|
|
|
144
|
|
|
/** |
145
|
|
|
* @return void |
146
|
|
|
*/ |
147
|
|
|
public static function set_late_hooks() |
148
|
|
|
{ |
149
|
|
|
add_filter( |
150
|
|
|
'FHEE__Single_Page_Checkout__translate_js_strings__ajax_submit', |
151
|
|
|
array('EED_Recaptcha', 'not_a_robot') |
152
|
|
|
); |
153
|
|
|
} |
154
|
|
|
|
155
|
|
|
|
156
|
|
|
/** |
157
|
|
|
* @return boolean |
158
|
|
|
*/ |
159
|
|
|
public static function useRecaptcha() |
160
|
|
|
{ |
161
|
|
|
return EED_Recaptcha::$config->use_captcha |
162
|
|
|
&& EED_Recaptcha::$config->recaptcha_theme !== 'invisible'; |
163
|
|
|
} |
164
|
|
|
|
165
|
|
|
|
166
|
|
|
/** |
167
|
|
|
* @return boolean |
168
|
|
|
* @throws InvalidArgumentException |
169
|
|
|
* @throws InvalidInterfaceException |
170
|
|
|
* @throws InvalidDataTypeException |
171
|
|
|
*/ |
172
|
|
|
public static function notPaymentOptionsRevisit() |
173
|
|
|
{ |
174
|
|
|
return ! ( |
175
|
|
|
EE_Registry::instance()->REQ->get('step', '') === 'payment_options' |
176
|
|
|
&& (boolean) EE_Registry::instance()->REQ->get('revisit', false) === true |
177
|
|
|
); |
178
|
|
|
} |
179
|
|
|
|
180
|
|
|
|
181
|
|
|
/** |
182
|
|
|
* @return void |
183
|
|
|
* @throws InvalidArgumentException |
184
|
|
|
* @throws InvalidInterfaceException |
185
|
|
|
* @throws InvalidDataTypeException |
186
|
|
|
*/ |
187
|
|
|
public static function enqueue_styles_and_scripts() |
188
|
|
|
{ |
189
|
|
|
wp_register_script( |
190
|
|
|
'espresso_recaptcha', |
191
|
|
|
RECAPTCHA_BASE_URL . 'scripts' . DS . 'espresso_recaptcha.js', |
192
|
|
|
array('single_page_checkout'), |
193
|
|
|
EVENT_ESPRESSO_VERSION, |
194
|
|
|
true |
195
|
|
|
); |
196
|
|
|
wp_register_script( |
197
|
|
|
'google_recaptcha', |
198
|
|
|
'https://www.google.com/recaptcha/api.js?hl=' . EED_Recaptcha::$config->recaptcha_language, |
199
|
|
|
array('espresso_recaptcha'), |
200
|
|
|
EVENT_ESPRESSO_VERSION, |
201
|
|
|
true |
202
|
|
|
); |
203
|
|
|
EE_Registry::$i18n_js_strings['no_SPCO_error'] = __( |
204
|
|
|
'It appears the Single Page Checkout javascript was not loaded properly! Please refresh the page and try again or contact support.', |
205
|
|
|
'event_espresso' |
206
|
|
|
); |
207
|
|
|
EE_Registry::$i18n_js_strings['no_recaptcha_error'] = __( |
208
|
|
|
'There appears to be a problem with the reCAPTCHA configuration! Please check the admin settings or contact support.', |
209
|
|
|
'event_espresso' |
210
|
|
|
); |
211
|
|
|
EE_Registry::$i18n_js_strings['recaptcha_fail'] = __( |
212
|
|
|
'Please complete the anti-spam test before proceeding.', |
213
|
|
|
'event_espresso' |
214
|
|
|
); |
215
|
|
|
} |
216
|
|
|
|
217
|
|
|
|
218
|
|
|
/** |
219
|
|
|
* @param \WP $WP |
220
|
|
|
*/ |
221
|
|
|
public function run($WP) |
222
|
|
|
{ |
223
|
|
|
} |
224
|
|
|
|
225
|
|
|
|
226
|
|
|
/** |
227
|
|
|
* @return boolean |
228
|
|
|
* @throws InvalidArgumentException |
229
|
|
|
* @throws InvalidInterfaceException |
230
|
|
|
* @throws InvalidDataTypeException |
231
|
|
|
*/ |
232
|
|
|
public static function not_a_robot() |
233
|
|
|
{ |
234
|
|
|
$not_a_robot = is_bool(EED_Recaptcha::$_not_a_robot) |
235
|
|
|
? EED_Recaptcha::$_not_a_robot |
236
|
|
|
: EED_Recaptcha::recaptcha_passed(); |
237
|
|
|
return $not_a_robot; |
238
|
|
|
} |
239
|
|
|
|
240
|
|
|
|
241
|
|
|
/** |
242
|
|
|
* @return void |
243
|
|
|
* @throws DomainException |
244
|
|
|
* @throws InvalidArgumentException |
245
|
|
|
* @throws InvalidInterfaceException |
246
|
|
|
* @throws InvalidDataTypeException |
247
|
|
|
*/ |
248
|
|
|
public static function display_recaptcha() |
249
|
|
|
{ |
250
|
|
|
// logged in means you have already passed a turing test of sorts |
251
|
|
|
if (is_user_logged_in()) { |
252
|
|
|
return; |
253
|
|
|
} |
254
|
|
|
// don't display if not using recaptcha or user is logged in |
255
|
|
|
if (EED_Recaptcha::useRecaptcha() && ! EED_Recaptcha::$_not_a_robot) { |
256
|
|
|
// only display if they have NOT passed the test yet |
257
|
|
|
EEH_Template::display_template( |
258
|
|
|
RECAPTCHA_BASE_PATH . DS . 'templates' . DS . 'recaptcha.template.php', |
259
|
|
|
array( |
260
|
|
|
'recaptcha_publickey' => EED_Recaptcha::$config->recaptcha_publickey, |
261
|
|
|
'recaptcha_theme' => EED_Recaptcha::$config->recaptcha_theme, |
262
|
|
|
'recaptcha_type' => EED_Recaptcha::$config->recaptcha_type, |
263
|
|
|
) |
264
|
|
|
); |
265
|
|
|
wp_enqueue_script('google_recaptcha'); |
266
|
|
|
} |
267
|
|
|
} |
268
|
|
|
|
269
|
|
|
|
270
|
|
|
/** |
271
|
|
|
* @return array |
272
|
|
|
* @throws InvalidArgumentException |
273
|
|
|
* @throws InvalidInterfaceException |
274
|
|
|
* @throws InvalidDataTypeException |
275
|
|
|
*/ |
276
|
|
|
public static function bypass_recaptcha_for_spco_load_payment_method() |
277
|
|
|
{ |
278
|
|
|
return array( |
279
|
|
|
'EESID' => EE_Registry::instance()->SSN->id(), |
280
|
|
|
'step' => 'payment_options', |
281
|
|
|
'action' => 'switch_spco_billing_form', |
282
|
|
|
); |
283
|
|
|
} |
284
|
|
|
|
285
|
|
|
|
286
|
|
|
/** |
287
|
|
|
* @return boolean |
288
|
|
|
* @throws InvalidArgumentException |
289
|
|
|
* @throws InvalidInterfaceException |
290
|
|
|
* @throws InvalidDataTypeException |
291
|
|
|
*/ |
292
|
|
|
public static function recaptcha_passed() |
293
|
|
|
{ |
294
|
|
|
// logged in means you have already passed a turing test of sorts |
295
|
|
|
if (is_user_logged_in() || EED_Recaptcha::_bypass_recaptcha()) { |
296
|
|
|
return true; |
297
|
|
|
} |
298
|
|
|
// was test already passed? |
299
|
|
|
$recaptcha_passed = EE_Registry::instance()->SSN->get_session_data('recaptcha_passed'); |
300
|
|
|
$recaptcha_passed = filter_var($recaptcha_passed, FILTER_VALIDATE_BOOLEAN); |
301
|
|
|
// verify recaptcha |
302
|
|
|
EED_Recaptcha::_get_recaptcha_response(); |
303
|
|
|
if (! $recaptcha_passed && EED_Recaptcha::$_recaptcha_response) { |
304
|
|
|
$recaptcha_passed = EED_Recaptcha::_process_recaptcha_response(); |
305
|
|
|
EE_Registry::instance()->SSN->set_session_data(array('recaptcha_passed' => $recaptcha_passed)); |
306
|
|
|
} |
307
|
|
|
EED_Recaptcha::$_not_a_robot = $recaptcha_passed; |
308
|
|
|
return $recaptcha_passed; |
309
|
|
|
} |
310
|
|
|
|
311
|
|
|
|
312
|
|
|
/** |
313
|
|
|
* @param array $recaptcha_response |
314
|
|
|
* @return array |
315
|
|
|
*/ |
316
|
|
|
public static function recaptcha_response($recaptcha_response = array()) |
317
|
|
|
{ |
318
|
|
|
if (EED_Recaptcha::_bypass_recaptcha()) { |
319
|
|
|
$recaptcha_response['bypass_recaptcha'] = true; |
320
|
|
|
$recaptcha_response['recaptcha_passed'] = true; |
321
|
|
|
} else { |
322
|
|
|
$recaptcha_response['recaptcha_passed'] = EED_Recaptcha::$_not_a_robot; |
323
|
|
|
} |
324
|
|
|
return $recaptcha_response; |
325
|
|
|
} |
326
|
|
|
|
327
|
|
|
|
328
|
|
|
/** |
329
|
|
|
* @return boolean |
330
|
|
|
*/ |
331
|
|
|
private static function _bypass_recaptcha() |
332
|
|
|
{ |
333
|
|
|
// an array of key value pairs that must match exactly with the incoming request, |
334
|
|
|
// in order to bypass recaptcha for the current request ONLY |
335
|
|
|
$bypass_request_params_array = (array) apply_filters( |
336
|
|
|
'FHEE__EED_Recaptcha___bypass_recaptcha__bypass_request_params_array', |
337
|
|
|
array() |
338
|
|
|
); |
339
|
|
|
// does $bypass_request_params_array have any values ? |
340
|
|
|
if (empty($bypass_request_params_array)) { |
341
|
|
|
return false; |
342
|
|
|
} |
343
|
|
|
// initially set bypass to TRUE |
344
|
|
|
$bypass_recaptcha = true; |
345
|
|
|
foreach ($bypass_request_params_array as $key => $value) { |
346
|
|
|
// if $key is not found or value doesn't match exactly, then toggle bypass to FALSE, |
347
|
|
|
// otherwise carry over it's value. This way, one missed setting results in no bypass |
348
|
|
|
$bypass_recaptcha = isset($_REQUEST[ $key ]) && $_REQUEST[ $key ] === $value |
349
|
|
|
? $bypass_recaptcha |
350
|
|
|
: false; |
351
|
|
|
} |
352
|
|
|
return $bypass_recaptcha; |
353
|
|
|
} |
354
|
|
|
|
355
|
|
|
|
356
|
|
|
/** |
357
|
|
|
* @return void |
358
|
|
|
* @throws InvalidArgumentException |
359
|
|
|
* @throws InvalidInterfaceException |
360
|
|
|
* @throws InvalidDataTypeException |
361
|
|
|
*/ |
362
|
|
|
private static function _get_recaptcha_response() |
363
|
|
|
{ |
364
|
|
|
EED_Recaptcha::$_recaptcha_response = EE_Registry::instance()->REQ->get( |
365
|
|
|
'g-recaptcha-response', |
366
|
|
|
false |
367
|
|
|
); |
368
|
|
|
} |
369
|
|
|
|
370
|
|
|
|
371
|
|
|
/** |
372
|
|
|
* @return boolean |
373
|
|
|
* @throws InvalidArgumentException |
374
|
|
|
* @throws InvalidInterfaceException |
375
|
|
|
* @throws InvalidDataTypeException |
376
|
|
|
*/ |
377
|
|
|
private static function _process_recaptcha_response() |
378
|
|
|
{ |
379
|
|
|
// verify library is loaded |
380
|
|
|
if (! class_exists('\ReCaptcha\ReCaptcha')) { |
381
|
|
|
require_once RECAPTCHA_BASE_PATH . DS . 'autoload.php'; |
382
|
|
|
} |
383
|
|
|
// The response from reCAPTCHA |
384
|
|
|
EED_Recaptcha::_get_recaptcha_response(); |
385
|
|
|
$recaptcha_response = EED_Recaptcha::$_recaptcha_response; |
386
|
|
|
// Was there a reCAPTCHA response? |
387
|
|
|
if ($recaptcha_response) { |
388
|
|
|
// if allow_url_fopen is Off, then set a different request method |
389
|
|
|
$request_method = ! ini_get('allow_url_fopen') ? new SocketPost() : null; |
390
|
|
|
$recaptcha = new ReCaptcha( |
391
|
|
|
EED_Recaptcha::$config->recaptcha_privatekey, |
392
|
|
|
$request_method |
393
|
|
|
); |
394
|
|
|
$recaptcha_response = $recaptcha->verify( |
395
|
|
|
EED_Recaptcha::$_recaptcha_response, |
396
|
|
|
$_SERVER['REMOTE_ADDR'] |
397
|
|
|
); |
398
|
|
|
} |
399
|
|
|
return $recaptcha_response instanceof Response && $recaptcha_response->isSuccess(); |
400
|
|
|
} |
401
|
|
|
} |
402
|
|
|
// End of file EED_Recaptcha.module.php |
403
|
|
|
// Location: /modules/recaptcha/EED_Recaptcha.module.php |
404
|
|
|
|