PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / 5.7.2
Defender Security – Malware Scanner, Login Security & Firewall v5.7.2
6.3.0 6.2.3 6.2.4 6.2.0 6.2.1 6.2.2 6.1.0 5.3.1 5.4.0 5.4.1 5.5.0 5.5.1 5.6.0 5.6.1 5.6.2 5.7.0 5.7.1 5.7.2 5.8.0 5.8.1 5.9.0 6.0.0 6.0.1 3.0.1 3.1.0 All 141 releases
defender-security / src / model / setting / class-captcha.php

class-captcha.php in Defender Security – Malware Scanner, Login Security & Firewall 5.7.2, at src/model/setting/class-captcha.php

407 lines 9.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Handle Captcha settings.
4 *
5 * @package WP_Defender\Model\Setting
6 */
7
8 namespace WP_Defender\Model\Setting;
9
10 use Calotes\Model\Setting;
11
12 /**
13 * Model for Captcha settings.
14 */
15 class Captcha extends Setting {
16
17 /**
18 * Option name.
19 * We'll keep the current table for all Captcha for backward compatibility. There's no need to edit the table name to store settings in the database.
20 *
21 * @var string
22 */
23 protected $table = 'wd_recaptcha_settings';
24
25 /**
26 * Feature status.
27 *
28 * @var bool
29 * @defender_property
30 */
31 public $enabled = false;
32
33 /**
34 * Captcha Provider.
35 *
36 * @var string
37 * @defender_property
38 */
39 public $provider = 'recaptcha';
40
41 /**
42 * Active Captcha type.
43 *
44 * @var string
45 * @defender_property
46 * @rule required
47 * @rule in[v2_checkbox,v2_invisible,v3_recaptcha,turnstile]
48 */
49 public $active_type = 'v2_checkbox';
50
51 /**
52 * Data for v2 checkbox reCaptcha.
53 *
54 * @var array
55 * @defender_property
56 */
57 public $data_v2_checkbox;
58
59 /**
60 * Data for v2 invisible reCaptcha.
61 *
62 * @var array
63 * @defender_property
64 */
65 public $data_v2_invisible;
66
67 /**
68 * Data for v3 reCaptcha.
69 *
70 * @var array
71 * @defender_property
72 */
73 public $data_v3_recaptcha;
74
75 /**
76 * Data for Cloudflare Turnstile.
77 *
78 * @var array
79 * @defender_property
80 */
81 public $data_turnstile;
82
83 /**
84 * Language for Captcha.
85 *
86 * @var string
87 * @defender_property
88 * @rule required
89 */
90 public $language = '';
91
92 /**
93 * Message for reCaptcha.
94 *
95 * @var string
96 * @defender_property
97 * @sanitize sanitize_textarea_field
98 */
99 public $message = '';
100
101 /**
102 * Locations for Captcha.
103 *
104 * @var array
105 * @defender_property
106 * @rule required
107 */
108 public $locations = array();
109
110 /**
111 * Flag to detect WooCommerce.
112 *
113 * @var bool
114 * @defender_property
115 */
116 public $detect_woo = false;
117
118 /**
119 * Checked locations for WooCommerce.
120 *
121 * @var array
122 * @defender_property
123 * @rule required
124 */
125 public $woo_checked_locations = array();
126
127 /**
128 * Flag to detect BuddyPress.
129 *
130 * @var bool
131 * @defender_property
132 */
133 public $detect_buddypress = false;
134
135 /**
136 * Checked locations for BuddyPress.
137 *
138 * @var array
139 * @defender_property
140 * @rule required
141 */
142 public $buddypress_checked_locations = array();
143
144 /**
145 * Flag to disable Captcha for known users.
146 *
147 * @var bool
148 * @defender_property
149 */
150 public $disable_for_known_users = true;
151
152 /**
153 * Rules for validating the Captcha settings.
154 *
155 * @var array
156 */
157 protected $rules = array(
158 array( array( 'enabled', 'detect_woo', 'detect_buddypress' ), 'boolean' ),
159 array( array( 'active_type' ), 'in', array( 'v2_checkbox', 'v2_invisible', 'v3_recaptcha', 'turnstile' ) ),
160 );
161
162 /**
163 * Retrieves the default values for the Captcha settings.
164 *
165 * @return array An associative array containing the default values.
166 */
167 public function get_default_values(): array {
168 return array(
169 'message' => esc_html__( 'reCAPTCHA verification failed. Please try again.', 'defender-security' ),
170 'turnstile_message' => esc_html__( 'Turnstile verification failed. Please try again.', 'defender-security' ),
171 );
172 }
173
174 /**
175 * Load default values.
176 *
177 * @return void
178 */
179 protected function before_load(): void {
180 $default_values = $this->get_default_values();
181 $this->provider = 'recaptcha';
182 $this->message = $default_values['message'];
183 $this->language = 'automatic';
184 $this->data_v2_checkbox = array(
185 'key' => '',
186 'secret' => '',
187 'size' => 'normal',
188 'style' => 'light',
189 );
190 $this->data_v2_invisible = array(
191 'key' => '',
192 'secret' => '',
193 );
194 $this->data_v3_recaptcha = array(
195 'key' => '',
196 'secret' => '',
197 'threshold' => '0.5',
198 );
199 $this->data_turnstile = array(
200 'key' => '',
201 'secret' => '',
202 'size' => 'normal',
203 'style' => 'auto',
204 'message' => $default_values['turnstile_message'],
205 'language' => 'auto',
206 );
207 }
208
209 /**
210 * Checks if the given Captcha type is valid and has all the necessary data.
211 *
212 * @param string $active_type The Captcha type to check.
213 *
214 * @return bool Returns true if the Captcha type is valid and has all the necessary data, false otherwise.
215 */
216 private function check_captcha_type( string $active_type ): bool {
217 if (
218 'v2_checkbox' === $active_type
219 && '' !== $this->data_v2_checkbox['key']
220 && '' !== $this->data_v2_checkbox['secret']
221 ) {
222 return true;
223 } elseif (
224 'v2_invisible' === $active_type
225 && '' !== $this->data_v2_invisible['key']
226 && '' !== $this->data_v2_invisible['secret']
227 ) {
228 return true;
229 } elseif (
230 'v3_recaptcha' === $active_type
231 && '' !== $this->data_v3_recaptcha['key'] && '' !== $this->data_v3_recaptcha['secret']
232 ) {
233 return true;
234 } elseif (
235 'turnstile' === $active_type &&
236 '' !== $this->data_turnstile['key'] &&
237 '' !== $this->data_turnstile['secret']
238 ) {
239 return true;
240 } else {
241 return false;
242 }
243 }
244
245 /**
246 * Checks if the CAPTCHA is active.
247 *
248 * @return bool Returns true if the CAPTCHA is active, false otherwise.
249 */
250 public function is_active(): bool {
251 $hook_name = 'turnstile' === $this->active_type ? 'wd_turnstile_enable' : 'wd_recaptcha_enable';
252 return (bool) apply_filters(
253 $hook_name,
254 $this->enabled
255 && '' !== $this->active_type
256 && '' !== $this->language
257 // For each Captcha type.
258 && $this->check_captcha_type( $this->active_type )
259 );
260 }
261
262 /**
263 * Is activated any default location?
264 *
265 * @return bool
266 */
267 public function enable_default_location(): bool {
268 return array() !== $this->locations;
269 }
270
271 /**
272 * Level#2 check by any activated location. Only if the plugin is enabled.
273 *
274 * @return bool
275 */
276 public function enable_woo_location(): bool {
277 return $this->detect_woo && array() !== $this->woo_checked_locations;
278 }
279
280 /**
281 * Level#2 check by deactivated locations. Only if the plugin is enabled.
282 *
283 * @return bool
284 */
285 public function is_unchecked_woo_locations(): bool {
286 return $this->detect_woo && array() === $this->woo_checked_locations;
287 }
288
289 /**
290 * Level#1 check. If the plugin is disabled, there is no point further.
291 *
292 * @param bool $is_woo_activated Whether WooCommerce is activated or not.
293 *
294 * @return bool
295 */
296 public function check_woo_locations( $is_woo_activated ): bool {
297 if ( ! $is_woo_activated ) {
298 return false;
299 }
300
301 return $this->enable_woo_location();
302 }
303
304 /**
305 * Level#2 check by any activated location. Only if the plugin is enabled.
306 *
307 * @return bool
308 */
309 public function enable_buddypress_location(): bool {
310 return $this->detect_buddypress && array() !== $this->buddypress_checked_locations;
311 }
312
313 /**
314 * Level#2 check by deactivated locations. Only if the plugin is enabled.
315 *
316 * @return bool
317 */
318 public function is_unchecked_buddypress_locations(): bool {
319 return $this->detect_buddypress && array() === $this->buddypress_checked_locations;
320 }
321
322 /**
323 * Level#1 Checks if the BuddyPress locations are valid and have all the necessary data.
324 *
325 * @param bool $is_buddypress_activated Whether BuddyPress is activated or not.
326 *
327 * @return bool Returns true if the BuddyPress locations are valid and have all the necessary data, false otherwise.
328 */
329 public function check_buddypress_locations( $is_buddypress_activated ): bool {
330 if ( ! $is_buddypress_activated ) {
331 return false;
332 }
333
334 return $this->enable_buddypress_location();
335 }
336
337 /**
338 * Define settings labels.
339 *
340 * @return array
341 */
342 public function labels(): array {
343 return array(
344 'enabled' => self::get_module_name(),
345 'active_type' => esc_html__( 'Configure CAPTCHA', 'defender-security' ),
346 'v2_checkbox' => esc_html__( 'V2 Checkbox', 'defender-security' ),
347 'v2_invisible' => esc_html__( 'V2 Invisible', 'defender-security' ),
348 'v3_recaptcha' => esc_html__( 'reCAPTCHA V3', 'defender-security' ),
349 'language' => esc_html__( 'Language', 'defender-security' ),
350 'message' => esc_html__( 'Error Message', 'defender-security' ),
351 'locations' => esc_html__( 'CAPTCHA Locations', 'defender-security' ),
352 'detect_woo' => esc_html__( 'WooCommerce', 'defender-security' ),
353 'detect_buddypress' => esc_html__( 'BuddyPress', 'defender-security' ),
354 'disable_for_known_users' => esc_html__( 'Disable for logged in users', 'defender-security' ),
355 );
356 }
357
358 /**
359 * Validates the form after submission.
360 *
361 * @return void
362 */
363 protected function after_validate(): void {
364 // Case with multi errors.
365 if ( $this->is_unchecked_woo_locations() && $this->is_unchecked_buddypress_locations() ) {
366 // The text of the notation is only in the first key, but we add the number of keys depending on the disabled locations of the plugins.
367 $this->errors['enable_woo'] = esc_html__(
368 'You have enabled reCaptcha for more than one plugin. Please select at least one form location for each plugin and click Save Changes again.',
369 'defender-security'
370 );
371 $this->errors['enable_buddypress'] = '';
372 } else {
373 // Individual cases with plugins.
374 if ( $this->is_unchecked_woo_locations() ) {
375 $this->errors['enable_woo'] = esc_html__(
376 'reCAPTCHA for WooCommerce is enabled, but no WooCommerce forms are selected. Please select at least one WooCommerce form location and then click Save Changes again.',
377 'defender-security'
378 );
379 }
380 if ( $this->is_unchecked_buddypress_locations() ) {
381 $this->errors['enable_buddypress'] = esc_html__(
382 'reCAPTCHA for BuddyPress is enabled, but no BuddyPress forms are selected. Please select at least one BuddyPress form location and then click Save Changes again.',
383 'defender-security'
384 );
385 }
386 }
387 }
388
389 /**
390 * Disable for logged in users or enable.
391 *
392 * @return bool
393 */
394 public function display_for_known_users(): bool {
395 return ! ( $this->disable_for_known_users && is_user_logged_in() );
396 }
397
398 /**
399 * Get module name.
400 *
401 * @return string
402 */
403 public static function get_module_name(): string {
404 return esc_html__( 'CAPTCHA', 'defender-security' );
405 }
406 }
407