PluginProbe ʕ •ᴥ•ʔ
Advanced Google reCAPTCHA / 5.40
Advanced Google reCAPTCHA v5.40
5.40 5.39 trunk 1.0.1 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.15 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1 1.11 1.12 1.13 1.14 1.15 1.16 1.17 1.18 1.19 1.20 1.21 1.22 1.23 1.24 1.25 1.26 1.27 1.28 1.29 1.30 1.31 1.32 1.33 1.34 1.35
advanced-google-recaptcha / libs / functions.php
advanced-google-recaptcha / libs Last commit date
admin.php 4 months ago ajax.php 4 months ago functions.php 1 month ago setup.php 3 months ago stats.php 4 months ago utility.php 4 months ago
functions.php
1447 lines
1 <?php
2
3 /**
4 * WP Captcha
5 * https://getwpcaptcha.com/
6 * (c) WebFactory Ltd, 2022 - 2026, www.webfactoryltd.com
7 */
8
9 class WPCaptcha_Functions extends WPCaptcha
10 {
11 static $wp_login_php;
12
13 // auto download / install / activate WP 301 Redirects plugin
14 static function install_wp301()
15 {
16 check_ajax_referer('install_wp301');
17
18 if (false === current_user_can('administrator')) {
19 wp_die('Sorry, you have to be an admin to run this action.');
20 }
21
22 $plugin_slug = 'eps-301-redirects/eps-301-redirects.php';
23 $plugin_zip = 'https://downloads.wordpress.org/plugin/eps-301-redirects.latest-stable.zip';
24
25 @include_once ABSPATH . 'wp-admin/includes/plugin.php';
26 @include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
27 @include_once ABSPATH . 'wp-admin/includes/plugin-install.php';
28 @include_once ABSPATH . 'wp-admin/includes/file.php';
29 @include_once ABSPATH . 'wp-admin/includes/misc.php';
30 echo '<style>
31 body{
32 font-family: sans-serif;
33 font-size: 14px;
34 line-height: 1.5;
35 color: #444;
36 }
37 </style>';
38
39 echo '<div style="margin: 20px; color:#444;">';
40 echo 'If things are not done in a minute <a target="_parent" href="' . esc_url(admin_url('plugin-install.php?s=301%20redirects%20webfactory&tab=search&type=term')) . '">install the plugin manually via Plugins page</a><br><br>';
41 echo 'Starting ...<br><br>';
42
43 wp_cache_flush();
44 $upgrader = new Plugin_Upgrader();
45 echo 'Check if WP 301 Redirects is already installed ... <br />';
46 if (self::is_plugin_installed($plugin_slug)) {
47 echo 'WP 301 Redirects is already installed! <br /><br />Making sure it\'s the latest version.<br />';
48 $upgrader->upgrade($plugin_slug);
49 $installed = true;
50 } else {
51 echo 'Installing WP 301 Redirects.<br />';
52 $installed = $upgrader->install($plugin_zip);
53 }
54 wp_cache_flush();
55
56 if (!is_wp_error($installed) && $installed) {
57 echo 'Activating WP 301 Redirects.<br />';
58 $activate = activate_plugin($plugin_slug);
59
60 if (is_null($activate)) {
61 echo 'WP 301 Redirects Activated.<br />';
62
63 echo '<script>setTimeout(function() { top.location = "' . esc_url(admin_url('options-general.php?page=eps_redirects')) . '"; }, 1000);</script>';
64 echo '<br>If you are not redirected in a few seconds - <a href="' . esc_url(admin_url('options-general.php?page=eps_redirects')) . '" target="_parent">click here</a>.';
65 }
66 } else {
67 echo 'Could not install WP 301 Redirects. You\'ll have to <a target="_parent" href="' . esc_url(admin_url('plugin-install.php?s=301%20redirects%20webfactory&tab=search&type=term')) . '">download and install manually</a>.';
68 }
69
70 echo '</div>';
71 } // install_wp301
72
73
74 /**
75 * Check if given plugin is installed
76 *
77 * @param [string] $slug Plugin slug
78 * @return boolean
79 */
80 static function is_plugin_installed($slug)
81 {
82 if (!function_exists('get_plugins')) {
83 require_once ABSPATH . 'wp-admin/includes/plugin.php';
84 }
85 $all_plugins = get_plugins();
86
87 if (!empty($all_plugins[$slug])) {
88 return true;
89 } else {
90 return false;
91 }
92 } // is_plugin_installed
93
94
95 static function countFails($username = "")
96 {
97 global $wpdb;
98 $options = WPCaptcha_Setup::get_options();
99 $ip = WPCaptcha_Utility::getUserIP();
100
101 // phpcs:ignore db call warning as we are using a custom table
102 $numFails = $wpdb->get_var( // phpcs:ignore
103 $wpdb->prepare(
104 "SELECT COUNT(login_attempt_ID) FROM " . $wpdb->wpcatcha_login_fails . " WHERE login_attempt_date + INTERVAL %d MINUTE > %s AND login_attempt_IP = %s",
105 array($options['retries_within'], current_time('mysql'), $ip)
106 )
107 );
108
109 return $numFails;
110 }
111
112 static function incrementFails($username = "", $reason = "")
113 {
114 global $wpdb;
115 $options = WPCaptcha_Setup::get_options();
116 $ip = WPCaptcha_Utility::getUserIP();
117
118 $username = sanitize_user($username);
119 $user = get_user_by('login', $username);
120
121 if ($user || 1 == $options['lockout_invalid_usernames']) {
122 if ($user === false) {
123 $user_id = -1;
124 } else {
125 $user_id = $user->ID;
126 }
127
128 // phpcs:ignore db call warning as we are using a custom table
129 $wpdb->insert( // phpcs:ignore
130 $wpdb->wpcatcha_login_fails,
131 array(
132 'user_id' => $user_id,
133 'login_attempt_date' => current_time('mysql'),
134 'login_attempt_IP' => $ip,
135 'failed_user' => $username,
136 'reason' => $reason
137 )
138 );
139 }
140 }
141
142 static function lockDown($username = "", $reason = "")
143 {
144 global $wpdb;
145 $options = WPCaptcha_Setup::get_options();
146 $ip = WPCaptcha_Utility::getUserIP();
147
148 $username = sanitize_user($username);
149 $user = get_user_by('login', $username);
150 if ($user || 1 == $options['lockout_invalid_usernames']) {
151 if ($user === false) {
152 $user_id = -1;
153 } else {
154 $user_id = $user->ID;
155 }
156
157 // phpcs:ignore db call warning as we are using a custom table
158 $wpdb->insert( // phpcs:ignore
159 $wpdb->wpcatcha_accesslocks,
160 array(
161 'user_id' => $user_id,
162 'accesslock_date' => current_time('mysql'),
163 'release_date' => gmdate('Y-m-d H:i:s', strtotime(current_time('mysql')) + $options['lockout_length'] * 60),
164 'accesslock_IP' => $ip,
165 'reason' => $reason
166 )
167 );
168 }
169 }
170
171 static function isLockedDown()
172 {
173 global $wpdb;
174 $ip = WPCaptcha_Utility::getUserIP();
175
176 // phpcs:ignore db call warning as we are using a custom table
177 $stillLocked = $wpdb->get_var($wpdb->prepare("SELECT user_id FROM " . $wpdb->wpcatcha_accesslocks . " WHERE release_date > %s AND accesslock_IP = %s AND unlocked = 0", array(current_time('mysql'), $ip))); // phpcs:ignore
178
179 return $stillLocked;
180 }
181
182 static function is_rest_request()
183 {
184 // no need for nonce check here
185 if (defined('REST_REQUEST') && REST_REQUEST || isset($_GET['rest_route']) && strpos(sanitize_text_field(wp_unslash($_GET['rest_route'])), '/', 0) === 0) { // phpcs:ignore
186 return true;
187 }
188
189 global $wp_rewrite;
190 if (null === $wp_rewrite) {
191 $wp_rewrite = new WP_Rewrite();
192 }
193
194 $rest_url = wp_parse_url(trailingslashit(rest_url()));
195 $current_url = wp_parse_url(add_query_arg(array()));
196 $is_rest = false;
197 if (isset($current_url['path'])) {
198 $is_rest = strpos($current_url['path'], $rest_url['path'], 0) === 0;
199 }
200
201 return $is_rest;
202 }
203
204 static function wp_authenticate_username_password($user, $username, $password)
205 {
206 $options = WPCaptcha_Setup::get_options();
207
208 if ($options['login_protection'] && self::isLockedDown()) {
209 self::accesslock_screen($options['block_message']);
210 return new WP_Error('wpcaptcha_fail_count', __("<strong>ERROR</strong>: We're sorry, but this IP has been blocked due to too many recent failed login attempts.<br /><br />Please try again later.", 'advanced-google-recaptcha'));
211 }
212
213 if (is_wp_error($user)) {
214 return $user;
215 }
216
217 if (!$username) {
218 return $user;
219 }
220
221 if (self::is_rest_request()) {
222 return $user;
223 }
224
225 if ($options['captcha_show_login']) {
226 $captcha = self::handle_captcha();
227 if (is_wp_error($captcha)) {
228 if ($options['max_login_retries'] <= self::countFails($username) && self::countFails($username) > 0) {
229 self::lockDown($username, 'Too many captcha fails');
230 }
231 return $captcha;
232 }
233 }
234
235 $userdata = get_user_by('login', $username);
236 if (false === $userdata) {
237 $userdata = get_user_by('email', $username);
238 }
239
240 if ($options['login_protection'] && $options['max_login_retries'] <= self::countFails($username)) {
241 if ($options['max_login_retries'] <= self::countFails($username) && self::countFails($username) > 0) {
242 self::lockDown($username, 'Too many fails');
243 }
244
245 if (strlen($username) > 0 && $userdata === false && $options['instant_block_nonusers'] == '1' && self::countFails($username) > 0) {
246 self::lockDown($username, 'Invalid Username');
247 }
248
249 return new WP_Error('wpcaptcha_fail_count', __("<strong>ERROR</strong>: We're sorry, but this IP has been blocked due to too many recent failed login attempts.<br /><br />Please try again later.", 'advanced-google-recaptcha'));
250 }
251
252 if (empty($username) || empty($password)) {
253 $error = new WP_Error();
254
255 if (empty($username))
256 $error->add('empty_username', __('<strong>ERROR</strong>: The username field is empty.', 'advanced-google-recaptcha'));
257
258 if (empty($password))
259 $error->add('empty_password', __('<strong>ERROR</strong>: The password field is empty.', 'advanced-google-recaptcha'));
260
261 return $error;
262 }
263
264 if ($userdata === false) {
265 /* translators: %s is replaced with the lost password URL */
266 return new WP_Error('invalid_username', sprintf(__('<strong>ERROR</strong>: Invalid username. <a href="%s" title="Password Lost and Found">Lost your password</a>?', 'advanced-google-recaptcha'), site_url('wp-login.php?action=lostpassword', 'login')));
267 }
268
269 $userdata = apply_filters('wp_authenticate_user', $userdata, $password);
270
271 if (is_wp_error($userdata)) {
272 return $userdata;
273 }
274
275 if (0 !== intval($userdata->user_status)) {
276 return new WP_Error('incorrect_password', __('<strong>ERROR</strong>: Inactive account', 'advanced-google-recaptcha'));
277 }
278
279 if (!is_string($password) || !is_string($userdata->user_pass) || is_null($userdata->ID) || !wp_check_password($password, $userdata->user_pass, $userdata->ID)) {
280 /* translators: %s is replaced with the lost password URL */
281 return new WP_Error('incorrect_password', sprintf(__('<strong>ERROR</strong>: Incorrect password. <a href="%s" title="Password Lost and Found">Lost your password</a>?', 'advanced-google-recaptcha'), site_url('wp-login.php?action=lostpassword', 'login')));
282 }
283
284 $user = new WP_User($userdata->ID);
285 return $user;
286 }
287
288 static function handle_captcha()
289 {
290 // no need for nonce check here, added phpcs:ignore to captcha $_POST variables
291 $options = WPCaptcha_Setup::get_options();
292 if ($options['captcha'] == 'recaptchav2') {
293 if (!isset($_POST['g-recaptcha-response']) || empty($_POST['g-recaptcha-response'])) { // phpcs:ignore
294 return new WP_Error('wpcaptcha_recaptchav2_not_submitted', __("<strong>ERROR</strong>: reCAPTCHA verification failed.<br /><br />Please try again.", 'advanced-google-recaptcha'));
295 } else {
296 $secret = $options['captcha_secret_key'];
297 $response = wp_remote_get('https://www.google.com/recaptcha/api/siteverify?secret=' . $secret . '&response=' . sanitize_text_field(wp_unslash($_POST['g-recaptcha-response']))); // phpcs:ignore
298 if (is_wp_error($response)) {
299 return new WP_Error('wpcaptcha_recaptchav3_failed', __("<strong>ERROR</strong>: reCAPTCHA verification request failed<br /><br />", 'advanced-google-recaptcha') . $response->get_error_message());
300 }
301 $response = json_decode($response['body']);
302 if ($response->success) {
303 return true;
304 } else {
305 return new WP_Error('wpcaptcha_recaptchav2_failed', __("<strong>ERROR</strong>: reCAPTCHA verification failed.<br /><br />Please try again.", 'advanced-google-recaptcha'));
306 }
307 }
308 } else if ($options['captcha'] == 'recaptchav3') {
309 if (!isset($_POST['g-recaptcha-response']) || empty($_POST['g-recaptcha-response'])) { // phpcs:ignore
310 return new WP_Error('wpcaptcha_recaptchav3_not_submitted', __("<strong>ERROR</strong>: reCAPTCHA verification failed.<br /><br />Please try again.", 'advanced-google-recaptcha'));
311 } else {
312
313 $secret = $options['captcha_secret_key'];
314 $response = wp_remote_get('https://www.google.com/recaptcha/api/siteverify?secret=' . $secret . '&response=' . sanitize_text_field(wp_unslash($_POST['g-recaptcha-response']))); // phpcs:ignore
315 if (is_wp_error($response)) {
316 return new WP_Error('wpcaptcha_recaptchav3_failed', __("<strong>ERROR</strong>: reCAPTCHA verification request failed<br /><br />", 'advanced-google-recaptcha') . $response->get_error_message());
317 }
318 $response = json_decode($response['body']);
319 if ($response->success && $response->score >= 0.5) {
320 return true;
321 } else {
322 return new WP_Error('wpcaptcha_recaptchav3_failed', __("<strong>ERROR</strong>: reCAPTCHA verification failed.<br /><br />Please try again.", 'advanced-google-recaptcha'));
323 }
324 }
325 } else if ($options['captcha'] == 'builtin') {
326 if (isset($_POST['wpcaptcha_captcha'])) { // phpcs:ignore
327 $captcha_responses = array_map('sanitize_text_field', wp_unslash($_POST['wpcaptcha_captcha'])); // phpcs:ignore
328 $captcha_tokens = array_map('sanitize_text_field', wp_unslash($_POST['wpcaptcha_captcha_token'])); // phpcs:ignore
329 foreach ($captcha_responses as $captcha_id => $captcha_val) {
330 if (wp_hash($captcha_val) === $captcha_tokens[$captcha_id]) {
331 return true;
332 } else {
333 return new WP_Error('wpcaptcha_builtin_captcha_failed', __("<strong>ERROR</strong>: captcha verification failed.<br /><br />Please try again.", 'advanced-google-recaptcha'));
334 }
335 }
336 } else {
337 return new WP_Error('wpcaptcha_builtin_captcha_failed', __("<strong>ERROR</strong>: captcha verification failed.<br /><br />Please try again.", 'advanced-google-recaptcha'));
338 }
339 }
340
341 return true;
342 }
343
344 static function handle_captcha_wp_registration($errors, $user_login, $user_email)
345 {
346 $captcha_check = self::handle_captcha();
347 if ($captcha_check !== true) {
348 $errors = $captcha_check;
349 }
350
351 return $errors;
352 }
353
354 static function process_lost_password_form($errors)
355 {
356 //phpcs:no nonce is set in the WordPress reset pass form
357 if( !isset( $_POST['pass1'] ) && !isset( $_POST['user_login'] ) ){ //phpcs:ignore
358 return $errors;
359 }
360
361 $captcha_check = self::handle_captcha();
362 if ($captcha_check !== true) {
363 $errors->add('captcha', $captcha_check->get_error_message());
364 }
365 }
366
367 static function check_woo_register_form_validation($validation_error)
368 {
369 if (wp_doing_ajax()) {
370 return $validation_error;
371 }
372
373 $captcha_check = self::handle_captcha();
374
375 if ($captcha_check !== true) {
376 if (isset($validation_error) && is_wp_error($validation_error)) {
377 $validation_error->add('captcha', $captcha_check->get_error_message());
378 return $validation_error;
379 } else {
380 wc_add_notice($captcha_check->get_error_message(), 'error');
381 return $validation_error;
382 }
383 }
384
385 return $validation_error;
386 }
387
388 static function check_woo_checkout_form()
389 {
390 $captcha_check = self::handle_captcha();
391 if ($captcha_check !== true) {
392 wc_add_notice($captcha_check->get_error_message(), 'error');
393 }
394 }
395
396 static function check_woo_order_pay()
397 {
398 $captcha_check = self::handle_captcha();
399 if ( $captcha_check === true ) {
400 return;
401 }
402
403 if ( function_exists('wc_add_notice') ) {
404 wc_add_notice($captcha_check->get_error_message(), 'error');
405 }
406 }
407
408 static function check_edd_register_form()
409 {
410 $captcha_check = self::handle_captcha();
411 if ($captcha_check !== true) {
412 edd_set_error('captcha', $captcha_check->get_error_message());
413 }
414 }
415
416 static function process_buddypress_signup_form()
417 {
418 $captcha_check = self::handle_captcha();
419 if ($captcha_check !== true) {
420 wp_die(
421 '<p><strong>' . esc_html__('ERROR:', 'advanced-google-recaptcha') . '</strong> ' . esc_html(wp_strip_all_tags($captcha_check->get_error_message())) . '</p>',
422 'reCAPTCHA',
423 array(
424 'response' => 403,
425 'back_link' => 1,
426 )
427 );
428 }
429 }
430
431 static function process_comment_form($commentdata)
432 {
433 // No need to check for loggedin user.
434 if (absint($commentdata['user_ID']) > 0) {
435 return $commentdata;
436 }
437
438 $captcha_check = self::handle_captcha();
439 if ($captcha_check !== true) {
440 wp_die(
441 '<p><strong>' . esc_html__('ERROR:', 'advanced-google-recaptcha') . '</strong> ' . esc_html(wp_strip_all_tags($captcha_check->get_error_message())) . '</p>',
442 'reCAPTCHA',
443 array(
444 'response' => 403,
445 'back_link' => 1,
446 )
447 );
448 }
449
450 return $commentdata;
451 }
452
453 static function loginFailed($username, $error)
454 {
455 self::incrementFails($username, $error->get_error_code());
456 }
457
458 static function login_error_message($error)
459 {
460 $options = WPCaptcha_Setup::get_options();
461
462 if ($options['mask_login_errors'] == 1) {
463 $error = 'Login Failed';
464 }
465 return $error;
466 }
467
468 static function login_form_fields()
469 {
470 $options = WPCaptcha_Setup::get_options();
471 $showcreditlink = $options['show_credit_link'];
472
473 if ($showcreditlink != "no" && $showcreditlink != 0) {
474 echo "<div id='wpcaptcha-protected-by' style='display: block; clear: both; padding-top: 20px; text-align: center;''>";
475 esc_html_e('Login form protected by', 'advanced-google-recaptcha');
476 echo " <a target='_blank' href='" . esc_url('https://getwpcaptcha.com/') . "'>WP Captcha</a></div>";
477 echo '<script>
478 document.addEventListener("DOMContentLoaded", function() {
479 document.querySelector("#loginform").append(document.querySelector("#wpcaptcha-protected-by"));
480 });
481 </script>';
482 }
483 }
484
485 static function captcha_fields_print()
486 {
487 //phpcs:ignore this just prints the recaptcha HTML inline and all variables are already escaped
488 echo self::captcha_fields(false); //phpcs:ignore
489 }
490
491 static function captcha_fields($output = false)
492 {
493 $options = WPCaptcha_Setup::get_options();
494
495 if(false === $output){
496 $output = '';
497 }
498 if ($options['captcha'] == 'recaptchav2') {
499 $output .= '<div class="g-recaptcha" style="transform: scale(0.9); -webkit-transform: scale(0.9); transform-origin: 0 0; -webkit-transform-origin: 0 0;" data-sitekey="' . esc_html($options['captcha_site_key']) . '"></div>';
500
501 if (class_exists('woocommerce')) {
502 $output .= '<script>
503 function wpcaptcha_captcha_refresh() {
504 grecaptcha.reset();
505 }
506
507 jQuery(document.body).on("checkout_error", function(){
508 setTimeout(wpcaptcha_captcha_refresh, 50);
509 });
510
511 jQuery(document.body).on("updated_checkout", function(){
512 setTimeout(wpcaptcha_captcha_refresh, 50);
513 });
514 </script>';
515 }
516 } else if ($options['captcha'] == 'recaptchav3') {
517 $output .= '<input type="hidden" name="g-recaptcha-response" class="agr-recaptcha-response" value="" />';
518 $output .= '<script>
519 (function() {
520 var siteKey = "' . esc_js($options['captcha_site_key']) . '";
521 var refreshTimer = null;
522
523 function wpcaptchaSetToken(token) {
524 document.querySelectorAll(".agr-recaptcha-response").forEach(function(field) {
525 field.value = token;
526 field.setAttribute("data-token-time", Date.now());
527 });
528 }
529
530 function wpcaptchaRefreshToken(callback) {
531 if (typeof grecaptcha === "undefined") {
532 if (callback) callback(false);
533 return;
534 }
535
536 grecaptcha.ready(function() {
537 grecaptcha.execute(siteKey, { action: "submit" }).then(function(token) {
538 wpcaptchaSetToken(token);
539 if (callback) callback(true);
540 });
541 });
542 }
543
544 function wpcaptchaStartAutoRefresh() {
545 clearInterval(refreshTimer);
546
547 wpcaptchaRefreshToken();
548
549 refreshTimer = setInterval(function() {
550 wpcaptchaRefreshToken();
551 }, 90000);
552 }
553
554 document.addEventListener("submit", function(e) {
555 var form = e.target;
556 var field = form.querySelector(".agr-recaptcha-response");
557
558 if (!field) return;
559
560 var tokenTime = parseInt(field.getAttribute("data-token-time") || "0", 10);
561 var age = Date.now() - tokenTime;
562
563 if (field.value && age < 90000) {
564 return;
565 }
566
567 e.preventDefault();
568
569 wpcaptchaRefreshToken(function(success) {
570 if (success) {
571 form.submit();
572 }
573 });
574 }, true);
575
576 window.wpcaptchaRefreshToken = wpcaptchaRefreshToken;
577
578 if (document.readyState === "loading") {
579 document.addEventListener("DOMContentLoaded", wpcaptchaStartAutoRefresh);
580 } else {
581 wpcaptchaStartAutoRefresh();
582 }
583 })();
584 </script>';
585 if (class_exists('woocommerce')) {
586 $output .= '<script>
587 jQuery(document.body).on("checkout_error", function(){
588 setTimeout(wpcaptchaRefreshToken, 50);
589 });
590
591 jQuery(document.body).on("updated_checkout", function(){
592 setTimeout(wpcaptchaRefreshToken, 50);
593 });
594 </script>';
595 }
596 } else if ($options['captcha'] == 'builtin') {
597 $output .= '<p><label for="wpcaptcha_captcha">' . !empty($options['captcha_challenge_text'])?$options['captcha_challenge_text']:'Are you human? Please solve: ';
598 $captcha_id = wp_rand(1000, 9999);
599 $captcha = self::math_captcha_generate($captcha_id);
600 $output .= '<img class="wpcaptcha-captcha-img" style="vertical-align: text-top;" src="' . $captcha['img'] . '" alt="Captcha" />';
601 $output .= '<input class="input" type="text" size="3" name="wpcaptcha_captcha[' . intval($captcha_id) . ']" id="wpcaptcha_captcha" value=""/>';
602 $output .= '<input type="hidden" name="wpcaptcha_captcha_token[' . intval($captcha_id) . ']" id="wpcaptcha_captcha_token" value="' . wp_hash($captcha['value']) . '" />';
603 $output .= '</label></p><br />';
604 }
605 return $output;
606 }
607
608 static function login_enqueue_scripts()
609 {
610 $options = WPCaptcha_Setup::get_options();
611 if ($options['captcha'] == 'recaptchav2') {
612 wp_enqueue_script('wpcaptcha-recaptcha', 'https://www.google.com/recaptcha/api.js', array('jquery'), self::$version, true);
613 } else if ($options['captcha'] == 'recaptchav3') {
614 wp_enqueue_script('wpcaptcha-recaptcha', 'https://www.google.com/recaptcha/api.js?onload=wpcaptchaRefreshToken&render=' . esc_html($options['captcha_site_key']), array('jquery'), self::$version, true);
615 }
616 }
617
618 static function login_scripts_print()
619 {
620 //phpcs:ignore this just prints the recaptcha scripts inline as they can be used in various forms where enqueing normally is not always working
621 echo self::login_scripts(false); //phpcs:ignore
622 }
623
624 static function login_scripts($output = false)
625 {
626 $options = WPCaptcha_Setup::get_options();
627
628 if(false === $output){
629 $output = '';
630 }
631 // scripts might need to be printed in odd contexts so wp_enqueue_script is not always ideal
632 if ($options['captcha'] == 'recaptchav2') {
633 $output .= "<script src='https://www.google.com/recaptcha/api.js?ver=" . esc_attr(self::$version) . "' id='wpcaptcha-recaptcha-js'></script>"; // phpcs:ignore
634 } else if ($options['captcha'] == 'recaptchav3') {
635 $output .= "<script src='https://www.google.com/recaptcha/api.js?render=" . esc_html($options['captcha_site_key']) . "&ver=" . esc_attr(self::$version) . "' id='wpcaptcha-recaptcha-js'></script>"; // phpcs:ignore
636 }
637
638 return $output;
639 }
640
641 static function accesslock_screen($block_message = false)
642 {
643 $main_color = '#4285f4';
644 $secondary_color = '#8eb8ff';
645
646 echo '<style>
647 @import url(\'https://fonts.bunny.net/css2?family=Roboto:ital,wght@0,300;0,400;0,500;0,700;1,400;1,500;1,700&display=swap\');
648
649 #wpcaptcha_accesslock_screen_wrapper{
650 font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;
651 width:100%;
652 height:100%;
653 position:fixed;
654 top:0;
655 left:0;
656 z-index: 999999;
657 font-size: 14px;
658 color: #333;
659 line-height: 1.4;
660 background-image: linear-gradient(45deg, ' . esc_attr($main_color) . ' 25%, ' . esc_attr($secondary_color) . ' 25%, ' . esc_attr($secondary_color) . ' 50%, ' . esc_attr($main_color) . ' 50%, ' . esc_attr($main_color) . ' 75%, ' . esc_attr($secondary_color) . ' 75%, ' . esc_attr($secondary_color) . ' 100%);
661 background-size: 28.28px 28.28px;
662 }
663
664 #wpcaptcha_accesslock_screen_wrapper form{
665 max-width: 300px;
666 top:50%;
667 left:50%;
668 margin-top:-200px;
669 margin-left:-200px;
670 border: none;
671 background: #ffffffde;
672 box-shadow: 0 1px 3px rgb(0 0 0 / 4%);
673 position: fixed;
674 text-align:center;
675 background: #fffffff2;
676 padding: 20px;
677 -webkit-box-shadow: 5px 5px 0px 1px rgba(0,0,0,0.22);
678 box-shadow: 5px 5px 0px 1px rgba(0,0,0,0.22);
679 }
680
681 #wpcaptcha_accesslock_screen_wrapper p{
682 padding: 10px;
683 line-height:1.5;
684 }
685
686 #wpcaptcha_accesslock_screen_wrapper p.error{
687 background: #f11c1c;
688 color: #FFF;
689 font-weight: 500;
690 }
691
692 #wpcaptcha_accesslock_screen_wrapper form input[type="text"]{
693 padding: 4px 10px;
694 border-radius: 2px;
695 border: 1px solid #c3c4c7;
696 font-size: 16px;
697 line-height: 1.33333333;
698 margin: 0 6px 16px 0;
699 min-height: 40px;
700 max-height: none;
701 width: 100%;
702 }
703
704 #wpcaptcha_accesslock_screen_wrapper form input[type="submit"]{
705 padding: 10px 10px;
706 border-radius: 2px;
707 border: none;
708 font-size: 16px;
709 background: ' . esc_attr($main_color) . ';
710 color: #FFF;
711 cursor: pointer;
712 width: 100%;
713 }
714
715 #wpcaptcha_accesslock_screen_wrapper form input[type="submit"]:hover{
716 background: ' . esc_attr($secondary_color) . ';
717 }
718 </style>
719
720 <script>
721 document.title = "' . esc_html(get_bloginfo('name')) . '";
722 </script>';
723 echo '<div id="wpcaptcha_accesslock_screen_wrapper">';
724
725 echo '<form method="POST">';
726
727 if (isset($_POST['wpcaptcha_recovery_submit']) && isset($_POST['wpcaptcha_recovery_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['wpcaptcha_recovery_nonce'])), 'wpcaptcha_recovery')) {
728 $wpcaptcha_recovery_email = false;
729
730 if (isset($_POST['wpcaptcha_recovery_email']) && is_email(sanitize_email(wp_unslash($_POST['wpcaptcha_recovery_email'])))) {
731 $wpcaptcha_recovery_email = sanitize_email(wp_unslash($_POST['wpcaptcha_recovery_email']));
732 }
733
734 if (false === $wpcaptcha_recovery_email) {
735 $display_message = '<p class="error">Invalid email address.</p>';
736 } else {
737 $user = get_user_by('email', $wpcaptcha_recovery_email);
738 if (user_can($user, 'administrator')) {
739 $unblock_key = 'agr' . md5(wp_generate_password(24));
740 $unblock_attempts = get_transient('wpcaptcha_unlock_count_' . $user->ID);
741 if (!$unblock_attempts) {
742 $unblock_attempts = 0;
743 }
744
745 $unblock_attempts++;
746 set_transient('wpcaptcha_unlock_count_' . $user->ID, $unblock_attempts, HOUR_IN_SECONDS);
747
748 if ($unblock_attempts <= 3) {
749 set_transient('wpcaptcha_unlock_' . $unblock_key, $unblock_key, HOUR_IN_SECONDS);
750
751 $unblock_url = add_query_arg(array('wpcaptcha_unblock' => $unblock_key), wp_login_url());
752
753 $subject = 'WP Captcha unblock instructions for ' . site_url();
754 $message = '<p>The IP ' . WPCaptcha_Utility::getUserIP() . ' has been locked down and someone submitted an unblock request using your email address <strong>' . $wpcaptcha_recovery_email . '</strong></p>';
755 $message .= '<p>If this was you, and you have locked yourself out please click <a target="_blank" href="' . $unblock_url . '">this link</a> which is valid for 1 hour.</p>';
756 $message .= '<p>Please note that for security reasons, this will only unblock the IP of the person opening the link, not the IP of the person who submitted the unblock request. To unblock someone else please do so on the <a href="' . admin_url('options-general.php?page=wpcaptcha#wpcaptcha_activity') . '">WP Captcha Activity Page</p>';
757
758 add_filter('wp_mail_content_type', function () {
759 return "text/html";
760 });
761
762 wp_mail($user->user_email, $subject, $message);
763 }
764 } else {
765 //If no admin using the submitted email exists, ignore silently
766 }
767
768 if (isset($unblock_attempts) && $unblock_attempts > 3) {
769 $display_message = '<p class="error">You have already attempted to unblock yourself recently, please wait 1 hour before trying again.</p>';
770 } else {
771 $display_message = '<p>If an administrator having the email address <strong>' . $wpcaptcha_recovery_email . '</strong> exists, an email has been sent with instructions to regain access.</p>';
772 }
773 }
774 }
775
776 echo '<img src="' . esc_url(WPCAPTCHA_PLUGIN_URL) . 'images/wp-captcha-logo.png" alt="WP Captcha" height="60" title="WP Captcha">';
777
778 echo '<br />';
779 echo '<br />';
780 if ($block_message !== false) {
781 echo '<p class="error">' . esc_html($block_message) . '</p>';
782 } else {
783 echo '<p class="error">We\'re sorry, but your IP has been blocked due to too many recent failed login attempts.</p>';
784 }
785 if (!empty($display_message)) {
786 WPCaptcha_Utility::wp_kses_wf($display_message);
787 }
788 echo '<p>If you are a user with administrative privilege please enter your email below to receive instructions on how to unblock yourself.</p>';
789 echo '<input type="text" name="wpcaptcha_recovery_email" value="" placeholder="" />';
790 echo '<input type="submit" name="wpcaptcha_recovery_submit" value="Send unblock email" placeholder="" />';
791 wp_nonce_field('wpcaptcha_recovery', 'wpcaptcha_recovery_nonce');
792
793
794 echo '</form>';
795 echo '</div>';
796
797 exit();
798 }
799
800 static function handle_unblock()
801 {
802 global $wpdb;
803 $options = WPCaptcha_Setup::get_options();
804 // no need for nonce check here as URL can be entered manually
805 if (isset($_GET['wpcaptcha_unblock']) && $options['global_unblock_key'] === $_GET['wpcaptcha_unblock']) { // phpcs:ignore
806 $user_ip = WPCaptcha_Utility::getUserIP();
807 if (!in_array($user_ip, $options['whitelist'])) {
808 $options['whitelist'][] = WPCaptcha_Utility::getUserIP();
809 }
810 update_option(WPCAPTCHA_OPTIONS_KEY, $options);
811 }
812
813
814
815 if (isset($_GET['wpcaptcha_unblock']) && strlen(sanitize_text_field(wp_unslash($_GET['wpcaptcha_unblock']))) == 32) { // phpcs:ignore
816 $unblock_key = sanitize_key($_GET['wpcaptcha_unblock']); // phpcs:ignore
817 $unblock_transient = get_transient('wpcaptcha_unlock_' . $unblock_key);
818 if ($unblock_transient == $unblock_key) {
819 $user_ip = WPCaptcha_Utility::getUserIP();
820
821 // phpcs:ignore db call warning as we are using a custom table
822 $wpdb->delete( // phpcs:ignore
823 $wpdb->wpcatcha_accesslocks,
824 array(
825 'accesslock_IP' => $user_ip
826 )
827 );
828
829 if (!in_array($user_ip, $options['whitelist'])) {
830 $options['whitelist'][] = WPCaptcha_Utility::getUserIP();
831 }
832
833 update_option(WPCAPTCHA_OPTIONS_KEY, $options);
834 }
835 }
836 }
837
838 static function wp_template_loader()
839 {
840 global $pagenow;
841 $pagenow = 'index.php';
842
843 if (!defined('WP_USE_THEMES')) {
844 define('WP_USE_THEMES', true);
845 }
846
847 wp();
848
849 require_once(ABSPATH . WPINC . '/template-loader.php');
850 die();
851 }
852
853 public static function pretty_fail_errors($error_code)
854 {
855 switch ($error_code) {
856 case 'wpcaptcha_location_blocked':
857 return 'Blocked Location';
858 break;
859 case 'wpcaptcha_fail_count':
860 return 'User exceeded maximum number of fails';
861 break;
862 case 'wpcaptcha_bot':
863 return 'Bot';
864 break;
865 case 'empty_username':
866 return 'Empty Username';
867 break;
868 case 'empty_password':
869 return 'Empty Password';
870 break;
871 case 'incorrect_password':
872 return 'Incorrect Password';
873 break;
874 case 'invalid_username':
875 return 'Invalid Username';
876 break;
877 case 'wpcaptcha_recaptchav2_not_submitted':
878 return 'reCAPTCHA v2 not submitted';
879 break;
880 case 'wpcaptcha_recaptchav3_not_submitted':
881 return 'reCAPTCHA v3 not submitted';
882 break;
883 case 'wpcaptcha_recaptchav2_failed':
884 return 'reCAPTCHA v2 failed verification';
885 break;
886 case 'wpcaptcha_recaptchav3_not_submitted':
887 return 'reCAPTCHA v3 failed verification';
888 break;
889 case 'wpcaptcha_builtin_captcha_failed':
890 return 'Built-in captcha failed verification';
891 break;
892 case 'wpcaptcha_hcaptcha_failed':
893 return 'hCaptcha failed verification';
894 break;
895 case 'wpcaptcha_icons_captcha_failed':
896 return 'Icon captcha failed verification';
897 default:
898 return 'Unknown';
899 break;
900 }
901 }
902
903 static function login_head()
904 {
905 $options = WPCaptcha_Setup::get_options();
906
907 if ($options['design_enable']) {
908 echo '<style type="text/css">';
909
910 add_filter('login_headerurl', function ($url) {
911 $options = WPCaptcha_Setup::get_options();
912 if (!empty($options['design_logo_url'])) {
913 return $options['design_logo_url'];
914 }
915 return $url;
916 });
917
918
919 if (!empty($options['design_logo'])) {
920 echo '#login h1 a, .login h1 a {';
921 echo 'filter: brightness(0) invert(1);';
922 echo '}';
923 }
924
925 if (!empty($options['design_background_color'])) {
926 echo 'body.login {background-color:' . esc_attr($options['design_background_color']) . '}';
927 }
928
929 if (!empty($options['design_background_image'])) {
930 echo 'body.login {background-image:url(' . esc_attr($options['design_background_image']) . '); background-size:cover;}';
931 }
932
933 echo 'body.login div#login form#loginform {';
934 if (!empty($options['design_form_width'])) {
935 echo 'width:' . (int)$options['design_form_width'] . 'px;';
936 }
937
938 if (!empty($options['design_form_height'])) {
939 echo 'height:' . (int)$options['design_form_height'] . 'px;';
940 }
941
942 if (!empty($options['design_form_padding'])) {
943 echo 'padding:' . (int)$options['design_form_padding'] . 'px;';
944 }
945
946 if (!empty($options['design_form_border_radius'])) {
947 echo 'border-radius:' . (int)$options['design_form_border_radius'] . 'px;';
948 }
949
950 if (!is_null($options['design_form_border_width'])) {
951 echo 'border-width:' . (int)$options['design_form_border_width'] . 'px;';
952 }
953
954 if (!empty($options['design_form_border_color'])) {
955 echo 'border-color:' . esc_attr($options['design_form_border_color']) . ';';
956 }
957
958 if (!empty($options['design_form_background_color'])) {
959 echo 'background-color:' . esc_attr($options['design_form_background_color']) . ';';
960 }
961
962 if (!empty($options['design_form_background_image'])) {
963 echo 'background-image:url(' . esc_url($options['design_form_background_image']) . '); background-size:cover;';
964 }
965 echo '}';
966
967 echo 'body.login div#login form#loginform label {';
968 if (!empty($options['design_label_font_size'])) {
969 echo 'font-size:' . (int)$options['design_label_font_size'] . 'px;';
970 }
971
972 if (!empty($options['design_label_text_color'])) {
973 echo 'color:' . esc_attr($options['design_label_text_color']) . ';';
974 }
975 echo '}';
976
977 echo 'body.login div#login form#loginform input {';
978 if (!empty($options['design_field_font_size'])) {
979 echo 'font-size:' . (int)$options['design_field_font_size'] . 'px;';
980 }
981
982 if (!empty($options['design_field_text_color'])) {
983 echo 'color:' . esc_attr($options['design_field_text_color']) . ';';
984 }
985
986 if (!empty($options['design_field_border_color'])) {
987 echo 'border-color:' . esc_attr($options['design_field_border_color']) . ';';
988 }
989
990 if (!is_null($options['design_field_border_width'])) {
991 echo 'border-width:' . (int)$options['design_field_border_width'] . 'px;';
992 }
993
994 if (!empty($options['design_field_border_radius'])) {
995 echo 'border-radius:' . (int)$options['design_field_border_radius'] . 'px;';
996 }
997
998 if (!empty($options['design_field_background_color'])) {
999 echo 'background-color:' . esc_attr($options['design_field_background_color']) . ';';
1000 }
1001 echo '}';
1002
1003 echo 'body.login div#login form#loginform p.submit input#wp-submit {';
1004 if (!empty($options['design_button_font_size'])) {
1005 echo 'font-size:' . (int)$options['design_button_font_size'] . 'px;';
1006 }
1007
1008 if (!empty($options['design_button_text_color'])) {
1009 echo 'color:' . esc_attr($options['design_button_text_color']) . ';';
1010 }
1011
1012 if (!empty($options['design_button_border_color'])) {
1013 echo 'border-color:' . esc_attr($options['design_button_border_color']) . ';';
1014 }
1015
1016 if (!is_null($options['design_button_border_width'])) {
1017 echo 'border-width:' . (int)$options['design_button_border_width'] . 'px;';
1018 }
1019
1020 if (!empty($options['design_button_border_radius'])) {
1021 echo 'border-radius:' . (int)$options['design_button_border_radius'] . 'px;';
1022 }
1023
1024 if (!empty($options['design_button_background_color'])) {
1025 echo 'background-color:' . esc_attr($options['design_button_background_color']) . ';';
1026 }
1027 echo '}';
1028
1029 echo 'body.login div#login form#loginform{';
1030 if (!empty($options['design_text_color'])) {
1031 echo 'color:' . esc_attr($options['design_text_color']) . ';';
1032 }
1033 echo '}';
1034
1035 echo 'body.login a, body.login #nav a, body.login #backtoblog a, body.login div#login form#loginform a{';
1036 if (!empty($options['design_link_color'])) {
1037 echo 'color:' . esc_attr($options['design_link_color']) . ';';
1038 }
1039 echo '}';
1040
1041 echo 'body.login a:hover, body.login #nav a:hover, body.login #backtoblog a:hover, body.login div#login form#loginform a:hover{';
1042 if (!empty($options['design_link_hover_color'])) {
1043 echo 'color:' . esc_attr($options['design_link_hover_color']) . ';';
1044 }
1045 echo '}';
1046
1047 echo 'body.login div#login form#loginform p.submit input#wp-submit:hover {';
1048 if (!empty($options['design_button_hover_text_color'])) {
1049 echo 'color:' . esc_attr($options['design_button_hover_text_color']) . ';';
1050 }
1051
1052 if (!empty($options['design_button_hover_border_color'])) {
1053 echo 'border-color:' . esc_attr($options['design_button_hover_border_color']) . ';';
1054 }
1055
1056 if (!empty($options['design_button_hover_background_color'])) {
1057 echo 'background-color:' . esc_attr($options['design_button_hover_background_color']) . ';';
1058 }
1059 echo '}';
1060
1061 echo '.wp-core-ui .button .dashicons, .wp-core-ui .button-secondary .dashicons{';
1062 if (!empty($options['design_link_color'])) {
1063 echo 'color:' . esc_attr($options['design_link_color']) . ';';
1064 }
1065 echo '}';
1066
1067 echo '.wp-core-ui .button .dashicons:hover, .wp-core-ui .button-secondary .dashicons:hover{';
1068 if (!empty($options['design_link_hover_color'])) {
1069 echo 'color:' . esc_attr($options['design_link_hover_color']) . ';';
1070 }
1071 echo '}';
1072
1073
1074 if (!empty($options['design_custom_css'])) {
1075 echo esc_html($options['design_custom_css']);
1076 }
1077
1078 echo '</style>';
1079 }
1080 }
1081
1082 static function get_templates()
1083 {
1084 $templates = array();
1085
1086 $templates['white'] = array(
1087 'design_background_color' => '#FFFFFF',
1088 'design_background_image' => '',
1089 'design_logo' => 'white-wpcaptcha-icon',
1090 'design_logo_width' => '100',
1091 'design_logo_height' => '100',
1092 'design_logo_margin_bottom' => '30',
1093 'design_text_color' => '#300000',
1094 'design_link_color' => '#06a8e8',
1095 'design_link_hover_color' => '#005b93',
1096 'design_form_border_color' => '#cbcbcb',
1097 'design_form_border_width' => '1',
1098 'design_form_width' => '',
1099 'design_form_height' => '',
1100 'design_form_padding' => '20',
1101 'design_form_border_radius' => '4',
1102 'design_form_background_color' => '#ffffff',
1103 'design_form_background_image' => '',
1104 'design_label_font_size' => '14',
1105 'design_label_text_color' => '#383838',
1106 'design_field_font_size' => '14',
1107 'design_field_text_color' => '#222222',
1108 'design_field_border_color' => '#d1d1d1',
1109 'design_field_border_width' => '1',
1110 'design_field_border_radius' => '2',
1111 'design_field_background_color' => '#ffffff',
1112 'design_button_font_size' => '14',
1113 'design_button_text_color' => '#ffffff',
1114 'design_button_border_color' => '#000000',
1115 'design_button_border_width' => '0',
1116 'design_button_border_radius' => '4',
1117 'design_button_background_color' => '#595959',
1118 'design_button_hover_text_color' => '#ffffff',
1119 'design_button_hover_border_color' => '#ffffff',
1120 'design_button_hover_background_color' => '#878787',
1121 'design_custom_css' => ''
1122 );
1123
1124 $templates['orange'] = array(
1125 'design_background_color' => '#ef9b00',
1126 'design_background_image' => '',
1127 'design_logo' => 'white-wpcaptcha-icon',
1128 'design_logo_width' => '100',
1129 'design_logo_height' => '100',
1130 'design_logo_margin_bottom' => '30',
1131 'design_text_color' => '#4c3d00',
1132 'design_link_color' => '#7c6e13',
1133 'design_link_hover_color' => '#896709',
1134 'design_form_border_color' => '#725f00',
1135 'design_form_border_width' => '0',
1136 'design_form_width' => '',
1137 'design_form_height' => '',
1138 'design_form_padding' => '20',
1139 'design_form_border_radius' => '4',
1140 'design_form_background_color' => '#f9e7ac',
1141 'design_form_background_image' => '',
1142 'design_label_font_size' => '14',
1143 'design_label_text_color' => '#634000',
1144 'design_field_font_size' => '14',
1145 'design_field_text_color' => '#222222',
1146 'design_field_border_color' => '#634000',
1147 'design_field_border_width' => '1',
1148 'design_field_border_radius' => '2',
1149 'design_field_background_color' => '#ffffff',
1150 'design_button_font_size' => '14',
1151 'design_button_text_color' => '#ffffff',
1152 'design_button_border_color' => '#634000',
1153 'design_button_border_width' => '1',
1154 'design_button_border_radius' => '4',
1155 'design_button_background_color' => '#634000',
1156 'design_button_hover_text_color' => '#ffffff',
1157 'design_button_hover_border_color' => '#8c5f00',
1158 'design_button_hover_background_color' => '#8c5f00',
1159 'design_custom_css' => ''
1160 );
1161
1162 $templates['red'] = array(
1163 'design_background_color' => '#ce0000',
1164 'design_background_image' => '',
1165 'design_logo' => 'white-wpcaptcha-icon',
1166 'design_logo_width' => '100',
1167 'design_logo_height' => '100',
1168 'design_logo_margin_bottom' => '30',
1169 'design_text_color' => '#300000',
1170 'design_link_color' => '#c91e1e',
1171 'design_link_hover_color' => '#d15959',
1172 'design_form_border_color' => '#c90000',
1173 'design_form_border_width' => '2',
1174 'design_form_width' => '',
1175 'design_form_height' => '',
1176 'design_form_padding' => '20',
1177 'design_form_border_radius' => '4',
1178 'design_form_background_color' => '#ffffff',
1179 'design_form_background_image' => '',
1180 'design_label_font_size' => '14',
1181 'design_label_text_color' => '#383838',
1182 'design_field_font_size' => '14',
1183 'design_field_text_color' => '#222222',
1184 'design_field_border_color' => '#d1d1d1',
1185 'design_field_border_width' => '1',
1186 'design_field_border_radius' => '2',
1187 'design_field_background_color' => '#ffffff',
1188 'design_button_font_size' => '14',
1189 'design_button_text_color' => '#ffffff',
1190 'design_button_border_color' => '#000000',
1191 'design_button_border_width' => '0',
1192 'design_button_border_radius' => '4',
1193 'design_button_background_color' => '#d30000',
1194 'design_button_hover_text_color' => '#ffffff',
1195 'design_button_hover_border_color' => '#ffffff',
1196 'design_button_hover_background_color' => '#9e0000',
1197 'design_custom_css' => ''
1198 );
1199
1200 $templates['green'] = array(
1201 'design_background_color' => '#2c6600',
1202 'design_background_image' => '',
1203 'design_logo' => 'white-icon.png',
1204 'design_logo_width' => '100',
1205 'design_logo_height' => '100',
1206 'design_logo_margin_bottom' => '30',
1207 'design_text_color' => '#c6e500',
1208 'design_link_color' => '#c6e500',
1209 'design_link_hover_color' => '#acbf00',
1210 'design_form_border_color' => '#c6e500',
1211 'design_form_border_width' => '2',
1212 'design_form_width' => '',
1213 'design_form_height' => '',
1214 'design_form_padding' => '20',
1215 'design_form_border_radius' => '4',
1216 'design_form_background_color' => '#4b7c01',
1217 'design_form_background_image' => '',
1218 'design_label_font_size' => '14',
1219 'design_label_text_color' => '#ffffff',
1220 'design_field_font_size' => '14',
1221 'design_field_text_color' => '#222222',
1222 'design_field_border_color' => '#87d642',
1223 'design_field_border_width' => '1',
1224 'design_field_border_radius' => '2',
1225 'design_field_background_color' => '#3c7f02',
1226 'design_button_font_size' => '14',
1227 'design_button_text_color' => '#ffffff',
1228 'design_button_border_color' => '#000000',
1229 'design_button_border_width' => '0',
1230 'design_button_border_radius' => '4',
1231 'design_button_background_color' => '#66b500',
1232 'design_button_hover_text_color' => '#ffffff',
1233 'design_button_hover_border_color' => '#ffffff',
1234 'design_button_hover_background_color' => '#a6d800',
1235 'design_custom_css' => ''
1236 );
1237
1238 $templates['blue'] = array(
1239 'design_background_color' => '#005cb2',
1240 'design_background_image' => '',
1241 'design_logo' => 'white-icon.png',
1242 'design_logo_width' => '100',
1243 'design_logo_height' => '100',
1244 'design_logo_margin_bottom' => '30',
1245 'design_text_color' => '#300000',
1246 'design_link_color' => '#2ca8ea',
1247 'design_link_hover_color' => '#005b93',
1248 'design_form_border_color' => '#008ed1',
1249 'design_form_border_width' => '2',
1250 'design_form_width' => '',
1251 'design_form_height' => '',
1252 'design_form_padding' => '20',
1253 'design_form_border_radius' => '4',
1254 'design_form_background_color' => '#ffffff',
1255 'design_form_background_image' => '',
1256 'design_label_font_size' => '14',
1257 'design_label_text_color' => '#383838',
1258 'design_field_font_size' => '14',
1259 'design_field_text_color' => '#222222',
1260 'design_field_border_color' => '#d1d1d1',
1261 'design_field_border_width' => '1',
1262 'design_field_border_radius' => '2',
1263 'design_field_background_color' => '#ffffff',
1264 'design_button_font_size' => '14',
1265 'design_button_text_color' => '#ffffff',
1266 'design_button_border_color' => '#000000',
1267 'design_button_border_width' => '0',
1268 'design_button_border_radius' => '4',
1269 'design_button_background_color' => '#0084cc',
1270 'design_button_hover_text_color' => '#ffffff',
1271 'design_button_hover_border_color' => '#ffffff',
1272 'design_button_hover_background_color' => '#005796',
1273 'design_custom_css' => ''
1274 );
1275
1276 $templates['gray'] = array(
1277 'design_background_color' => '#353535',
1278 'design_background_image' => '',
1279 'design_logo' => 'white-icon.png',
1280 'design_logo_width' => '100',
1281 'design_logo_height' => '100',
1282 'design_logo_margin_bottom' => '30',
1283 'design_text_color' => '#300000',
1284 'design_link_color' => '#06a8e8',
1285 'design_link_hover_color' => '#005b93',
1286 'design_form_border_color' => '#474747',
1287 'design_form_border_width' => '2',
1288 'design_form_width' => '',
1289 'design_form_height' => '',
1290 'design_form_padding' => '20',
1291 'design_form_border_radius' => '4',
1292 'design_form_background_color' => '#ffffff',
1293 'design_form_background_image' => '',
1294 'design_label_font_size' => '14',
1295 'design_label_text_color' => '#383838',
1296 'design_field_font_size' => '14',
1297 'design_field_text_color' => '#222222',
1298 'design_field_border_color' => '#d1d1d1',
1299 'design_field_border_width' => '1',
1300 'design_field_border_radius' => '2',
1301 'design_field_background_color' => '#ffffff',
1302 'design_button_font_size' => '14',
1303 'design_button_text_color' => '#ffffff',
1304 'design_button_border_color' => '#000000',
1305 'design_button_border_width' => '0',
1306 'design_button_border_radius' => '4',
1307 'design_button_background_color' => '#595959',
1308 'design_button_hover_text_color' => '#ffffff',
1309 'design_button_hover_border_color' => '#ffffff',
1310 'design_button_hover_background_color' => '#878787',
1311 'design_custom_css' => ''
1312 );
1313
1314 return $templates;
1315 }
1316
1317 static function install_template()
1318 {
1319 check_admin_referer('wpcaptcha_install_template');
1320 $options = WPCaptcha_Setup::get_options();
1321
1322 $template = false;
1323 if (isset($_GET['template'])) {
1324 $template = sanitize_key(wp_unslash($_GET['template']));
1325 }
1326
1327 $templates = self::get_templates();
1328
1329 if (array_key_exists($template, $templates)) {
1330 $options = array_merge($options, $templates[$template]);
1331 if ($options['design_logo'] == 'white-wpcaptcha-icon') {
1332 $options['design_logo'] = WPCAPTCHA_PLUGIN_URL . 'images/white-icon.png';
1333 }
1334
1335 $options['design_template'] = $template;
1336 $options['design_enable'] = 1;
1337 update_option(WPCAPTCHA_OPTIONS_KEY, $options);
1338 WPCaptcha_Admin::add_notice('template_activated', __('Template activated.', 'advanced-google-recaptcha'), 'success', true);
1339 } else {
1340 WPCaptcha_Admin::add_notice('template_not_found', __('Unknown template ID.', 'advanced-google-recaptcha'), 'error', true);
1341 }
1342
1343 if (!empty($_GET['redirect'])) {
1344 $redirect_url = sanitize_url(wp_unslash($_GET['redirect']));
1345 wp_safe_redirect($redirect_url);
1346 }
1347 }
1348
1349 // convert HEX(HTML) color notation to RGB
1350 static function hex2rgb($color)
1351 {
1352 if ($color[0] == '#') {
1353 $color = substr($color, 1);
1354 }
1355
1356 if (strlen($color) == 6) {
1357 list($r, $g, $b) = array(
1358 $color[0] . $color[1],
1359 $color[2] . $color[3],
1360 $color[4] . $color[5]
1361 );
1362 } elseif (strlen($color) == 3) {
1363 list($r, $g, $b) = array($color[0] . $color[0], $color[1] . $color[1], $color[2] . $color[2]);
1364 } else {
1365 return array(255, 255, 255);
1366 }
1367
1368 $r = hexdec($r);
1369 $g = hexdec($g);
1370 $b = hexdec($b);
1371
1372 return array($r, $g, $b);
1373 } // html2rgb
1374
1375
1376 // output captcha image
1377 static function math_captcha_generate($captcha_id = false)
1378 {
1379 ob_start();
1380
1381 $a = wp_rand(0, (int) 10);
1382 $b = wp_rand(0, (int) 10);
1383 if(isset($_GET['color'])){ // phpcs:ignore
1384 $color = substr($_GET['color'],0,7); // phpcs:ignore
1385 $color = urldecode($color);
1386 } else{
1387 $color = '#FFFFFF';
1388 }
1389
1390 if ($a > $b) {
1391 $out = "$a - $b";
1392 $captcha_value = $a - $b;
1393 } else {
1394 $out = "$a + $b";
1395 $captcha_value = $a + $b;
1396 }
1397
1398 $font = 5;
1399 $width = ImageFontWidth($font) * strlen($out);
1400 $height = ImageFontHeight($font);
1401 $im = ImageCreate($width, $height);
1402
1403 $x = imagesx($im) - $width;
1404 $y = imagesy($im) - $height;
1405
1406 $white = imagecolorallocate($im, 255, 255, 255);
1407 $gray = imagecolorallocate($im, 66, 66, 66);
1408 $black = imagecolorallocate($im, 0, 0, 0);
1409 $trans_color = $white; //transparent color
1410
1411 if ($color) {
1412 $color = self::hex2rgb($color);
1413 $new_color = imagecolorallocate($im, $color[0], $color[1], $color[2]);
1414 imagefill($im, 1, 1, $new_color);
1415 } else {
1416 imagecolortransparent($im, $trans_color);
1417 }
1418
1419 imagestring($im, $font, $x, $y, $out, $black);
1420
1421 // always add noise
1422 if (1 == 1) {
1423 $color_min = 100;
1424 $color_max = 200;
1425 $rand1 = imagecolorallocate($im, wp_rand($color_min, $color_max), wp_rand($color_min, $color_max), wp_rand($color_min, $color_max));
1426 $rand2 = imagecolorallocate($im, wp_rand($color_min, $color_max), wp_rand($color_min, $color_max), wp_rand($color_min, $color_max));
1427 $rand3 = imagecolorallocate($im, wp_rand($color_min, $color_max), wp_rand($color_min, $color_max), wp_rand($color_min, $color_max));
1428 $rand4 = imagecolorallocate($im, wp_rand($color_min, $color_max), wp_rand($color_min, $color_max), wp_rand($color_min, $color_max));
1429 $rand5 = imagecolorallocate($im, wp_rand($color_min, $color_max), wp_rand($color_min, $color_max), wp_rand($color_min, $color_max));
1430
1431 $style = array($rand1, $rand2, $rand3, $rand4, $rand5);
1432 imagesetstyle($im, $style);
1433 imageline($im, wp_rand(0, $width), 0, wp_rand(0, $width), $height, IMG_COLOR_STYLED);
1434 imageline($im, wp_rand(0, $width), 0, wp_rand(0, $width), $height, IMG_COLOR_STYLED);
1435 imageline($im, wp_rand(0, $width), 0, wp_rand(0, $width), $height, IMG_COLOR_STYLED);
1436 imageline($im, wp_rand(0, $width), 0, wp_rand(0, $width), $height, IMG_COLOR_STYLED);
1437 imageline($im, wp_rand(0, $width), 0, wp_rand(0, $width), $height, IMG_COLOR_STYLED);
1438 }
1439
1440 imagegif($im);
1441
1442 // Get image data
1443 $image_data = ob_get_clean();
1444 return array('value' => $captcha_value, 'img' => 'data:image/png;base64,' . base64_encode($image_data));
1445 } // create
1446 } // class
1447