PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / 6.2.1
Defender Security – Malware Scanner, Login Security & Firewall v6.2.1
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 / component / captcha / class-recaptcha.php

class-recaptcha.php in Defender Security – Malware Scanner, Login Security & Firewall 6.2.1, at src/component/captcha/class-recaptcha.php

331 lines 8.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * ReCAPTCHA provider implementation.
4 *
5 * @package WP_Defender\Component\Captcha
6 */
7
8 namespace WP_Defender\Component\Captcha;
9
10 use WP_Defender\Integrations\Buddypress;
11 use WP_Defender\Integrations\Woocommerce;
12
13 /**
14 * Google reCAPTCHA provider.
15 */
16 class Recaptcha extends Provider {
17
18 /**
19 * Get the request field name for responses.
20 *
21 * @return string
22 */
23 protected function get_response_field(): string {
24 return 'g-recaptcha-response';
25 }
26
27 /**
28 * Get script handle name.
29 *
30 * @return string
31 */
32 public function get_script_handle(): string {
33 return 'wpdef_recaptcha_script';
34 }
35
36 /**
37 * Get frontend script URL.
38 *
39 * @return string
40 */
41 public function get_script_url(): string {
42 return 'assets/js/recaptcha_frontend.js';
43 }
44
45 /**
46 * Get widget options.
47 *
48 * @return array
49 */
50 public function get_options(): array {
51 $options = array(
52 'version' => $this->type,
53 'sitekey' => $this->key,
54 'hl' => $this->language,
55 'size' => $this->size,
56 'error' => $this->get_duplicate_captcha_warning(),
57 // For default comment form.
58 'disable' => '',
59 );
60 if ( 'v2_checkbox' === $this->type ) {
61 $options['theme'] = $this->theme;
62 }
63
64 return $options;
65 }
66
67 /**
68 * Get provider name.
69 *
70 * @param bool $is_type Get provider name by type.
71 *
72 * @return string
73 */
74 public function get_name( bool $is_type = false ): string {
75 if ( $is_type ) {
76 return $this->model->labels()[ $this->type ];
77 }
78 return __( 'reCAPTCHA', 'defender-security' );
79 }
80
81 /**
82 * Get widget content HTML.
83 *
84 * @param int $id Unique widget id.
85 *
86 * @return string
87 */
88 protected function get_widget_content( int $id ): string {
89 $content = '';
90 if ( in_array( $this->type, array( 'v2_checkbox', 'v2_invisible' ), true ) ) {
91 $content .= sprintf(
92 '<div id="wpdef_recaptcha_%s" class="wpdef_recaptcha"></div>',
93 esc_attr( $id )
94 );
95 $content .= '<noscript>
96 <div style="width: 302px;">
97 <div style="width: 302px; height: 422px; position: relative;">
98 <div style="width: 302px; height: 422px; position: absolute;">
99 <iframe src="https://www.google.com/recaptcha/api/fallback?k=' . esc_attr( $this->key ) . '"
100 frameborder="0" scrolling="no" style="width: 302px; height:422px; border-style: none;"></iframe>
101 </div>
102 </div>
103 <div
104 style="bottom: 12px; left: 25px; margin: 0; padding: 0; right: 25px; background: #f9f9f9; border: 1px solid #c1c1c1; border-radius: 3px; height: 60px; width: 300px;">
105 <textarea name="g-recaptcha-response" class="g-recaptcha-response"
106 style="width: 250px !important; height: 40px !important; border: 1px solid #c1c1c1 !important; margin: 10px 25px !important; padding: 0 !important; resize: none !important;"></textarea>
107 </div>
108 </div>
109 </noscript>';
110 } elseif ( 'v3_recaptcha' === $this->type ) {
111 $content .= sprintf(
112 '<div id="wpdef_recaptcha_%s" class="wpdef_recaptcha"><input type="hidden" class="g-recaptcha-response" name="g-recaptcha-response" /></div>',
113 esc_attr( $id )
114 );
115 }
116
117 return $content;
118 }
119
120 /**
121 * Get API script configuration.
122 *
123 * @return array
124 */
125 public function get_api_script(): array {
126 return array(
127 'url' => $this->get_api_url(),
128 'deps' => 'v3_recaptcha' === $this->type ? array() : array( 'jquery' ),
129 'version' => DEFENDER_VERSION,
130 );
131 }
132
133 /**
134 * Get API script URL.
135 *
136 * @return string
137 */
138 public function get_api_url(): string {
139 if ( 'v3_recaptcha' === $this->type ) {
140 return sprintf(
141 'https://www.google.com/recaptcha/api.js?hl=%s&render=%s',
142 $this->language,
143 $this->key
144 );
145 }
146
147 return sprintf(
148 'https://www.google.com/recaptcha/api.js?hl=%s&render=explicit',
149 $this->language
150 );
151 }
152
153 /**
154 * Get verification URL.
155 *
156 * @return string
157 */
158 public function get_verify_url(): string {
159 return 'https://www.google.com/recaptcha/api/siteverify';
160 }
161
162 /**
163 * Get list of excluded requests.
164 *
165 * @return array
166 */
167 public function get_excluded_requests(): array {
168 $requests = $this->filter_excluded_requests();
169
170 /**
171 * Filters request slugs to exclude from reCAPTCHA checks.
172 *
173 * @param array $requests Request slugs to exclude.
174 *
175 * @since 2.5.6
176 * @deprecated 5.9.0 Use wd_captcha_excluded_requests instead.
177 */
178 $requests = apply_filters_deprecated(
179 'wd_recaptcha_excluded_requests',
180 array( $requests ),
181 '5.9.0',
182 'wd_captcha_excluded_requests',
183 __( 'Use wd_captcha_excluded_requests to filter excluded requests for all captcha providers.', 'defender-security' )
184 );
185
186 return is_array( $requests ) ? $requests : (array) $requests;
187 }
188
189 /**
190 * Get list of duplicate script handles.
191 *
192 * @return array
193 */
194 public function get_duplicate_script_handles(): array {
195 $handles = $this->filter_excluded_handles(
196 array(
197 'wpdef_captcha_api',
198 'forminator-google-recaptcha',
199 )
200 );
201
202 /**
203 * Filters script handles to exclude from reCAPTCHA duplication checks.
204 *
205 * @param array $handles Script handles to ignore when checking for duplicates.
206 *
207 * @since 2.5.6
208 * @deprecated 5.9.0 Use wd_captcha_excluded_handles instead.
209 */
210 $handles = apply_filters_deprecated(
211 'wd_recaptcha_excluded_handles',
212 array( $handles ),
213 '5.9.0',
214 'wd_captcha_excluded_handles',
215 __( 'Use wd_captcha_excluded_handles to filter excluded script handles for all captcha providers.', 'defender-security' )
216 );
217
218 return is_array( $handles ) ? $handles : (array) $handles;
219 }
220
221 /**
222 * Get regex pattern for duplicate scripts.
223 *
224 * @return string
225 */
226 public function get_duplicate_script_pattern(): string {
227 return '|google\.com/recaptcha/api\.js|';
228 }
229
230 /**
231 * Determine whether to skip checks for this form.
232 *
233 * @param Woocommerce $woo WooCommerce integration.
234 * @param Buddypress $buddypress BuddyPress integration.
235 *
236 * @return bool
237 */
238 public function should_skip_check( Woocommerce $woo, Buddypress $buddypress ): bool {
239 return false;
240 }
241
242 /**
243 * Verify response for a specific form.
244 *
245 * @param string $form Form identifier.
246 *
247 * @return bool
248 */
249 public function verify_response( string $form ): bool {
250 /**
251 * Filters the remote IP address for reCAPTCHA verification.
252 *
253 * @param string $user_ip The remote IP address.
254 *
255 * @since 2.5.6
256 * @deprecated 5.9.0 Use wd_captcha_remote_ip instead.
257 */
258 $user_ip = apply_filters_deprecated(
259 'wd_recaptcha_remote_ip',
260 array( $this->get_primary_ip() ),
261 '5.9.0',
262 'wd_captcha_remote_ip',
263 __( 'Use wd_captcha_remote_ip to filter remote IP for all captcha providers.', 'defender-security' )
264 );
265 $response_keys = $this->verify_response_token(
266 $this->get_response(),
267 $this->get_verify_url(),
268 array(
269 'remoteip' => is_string( $user_ip ) ? $user_ip : (string) $user_ip,
270 )
271 );
272 $response_success = (bool) ( $response_keys['success'] ?? false );
273 if ( 'v3_recaptcha' === $this->type && $response_success ) {
274 $score = (float) ( $response_keys['score'] ?? 0.0 );
275 $response_success = $score >= $this->threshold;
276 }
277
278 $response_success = $this->filter_check_result( $response_success, $form );
279
280 /**
281 * Filters the result of a reCAPTCHA verification.
282 *
283 * @param bool $response_success The result of the reCAPTCHA verification.
284 * @param string $form The form being verified.
285 *
286 * @since 2.5.6
287 * @deprecated 5.9.0 Use wd_captcha_check_result instead.
288 */
289 $result = apply_filters_deprecated(
290 'wd_recaptcha_check_result',
291 array( $response_success, $form ),
292 '5.9.0',
293 'wd_captcha_check_result',
294 __( 'Use wd_captcha_check_result to filter captcha verification for all providers.', 'defender-security' )
295 );
296 return is_bool( $result ) ? $result : (bool) $result;
297 }
298
299 /**
300 * Get provider settings from model.
301 *
302 * @return array
303 */
304 protected function get_data(): array {
305 $type_data_map = array(
306 'v3_recaptcha' => $this->model->data_v3_recaptcha ?? array(),
307 'v2_checkbox' => $this->model->data_v2_checkbox ?? array(),
308 'v2_invisible' => $this->model->data_v2_invisible ?? array(),
309 );
310
311 $data = $type_data_map[ $this->type ] ?? array();
312
313 $data = wp_parse_args(
314 $data,
315 array(
316 'key' => '',
317 'secret' => '',
318 'style' => '',
319 'size' => 'invisible',
320 'message' => '',
321 'threshold' => 0.0,
322 )
323 );
324
325 $defaults = $this->model->get_default_values();
326 $data['message'] = '' !== $this->model->message ? $this->model->message : $defaults['message'];
327
328 return $data;
329 }
330 }
331