PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 5.5.6
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v5.5.6
6.35 6.34 6.33.1 6.33 6.32.1 6.32 6.31 6.25 6.25.1 6.26 6.26.1 6.27 6.28 6.29 6.3 6.3.1 6.3.2 6.30 6.4 6.4.1 6.4.2 6.5 6.5.1 6.5.2 6.5.3 All 141 releases
formidable / classes / models / fields / FrmFieldCaptcha.php

FrmFieldCaptcha.php in Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More 5.5.6, at classes/models/fields/FrmFieldCaptcha.php

336 lines 9.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if ( ! defined( 'ABSPATH' ) ) {
3 die( 'You are not allowed to call this page directly.' );
4 }
5
6 /**
7 * @since 3.0
8 */
9 class FrmFieldCaptcha extends FrmFieldType {
10
11 /**
12 * @var string
13 * @since 3.0
14 */
15 protected $type = 'captcha';
16
17 /**
18 * @return string
19 */
20 protected function include_form_builder_file() {
21 return FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/field-captcha.php';
22 }
23
24 /**
25 * Returns the image name for a captcha.
26 *
27 * @return string
28 */
29 public static function get_captcha_image_name() {
30 $frm_settings = FrmAppHelper::get_settings();
31 $active_captcha = $frm_settings->active_captcha;
32 if ( ! self::should_show_captcha() ) {
33 $image_name = 'captcha_not_setup';
34 } elseif ( $active_captcha === 'recaptcha' && $frm_settings->re_type === 'v3' ) {
35 $image_name = 'recaptcha_v3';
36 } else {
37 $image_name = $active_captcha;
38 }
39
40 return $image_name;
41 }
42
43 /**
44 * @return array
45 */
46 protected function field_settings_for_type() {
47 return array(
48 'required' => false,
49 'invalid' => true,
50 'captcha_size' => true,
51 'default' => false,
52 );
53 }
54
55 /**
56 * @return array
57 */
58 protected function new_field_settings() {
59 $frm_settings = FrmAppHelper::get_settings();
60
61 return array(
62 'invalid' => $frm_settings->re_msg,
63 );
64 }
65
66 /**
67 * @return array
68 */
69 protected function extra_field_opts() {
70 return array(
71 'label' => 'none',
72 'captcha_size' => 'normal',
73 'captcha_theme' => 'light',
74 );
75 }
76
77 /**
78 * Remove the "for" attribute for captcha
79 *
80 * @param array $args
81 * @param string $html
82 *
83 * @return string
84 */
85 protected function before_replace_html_shortcodes( $args, $html ) {
86 $frm_settings = FrmAppHelper::get_settings();
87 $replace_response = $frm_settings->active_captcha === 'recaptcha' ? 'g-recaptcha-response' : 'h-captcha-response';
88 $replaced_for = str_replace( ' for="field_[key]"', ' for="' . $replace_response . '"', $html );
89
90 return $replaced_for;
91 }
92
93 public function front_field_input( $args, $shortcode_atts ) {
94 $frm_settings = FrmAppHelper::get_settings();
95 if ( ! self::should_show_captcha() ) {
96 return '';
97 }
98
99 $class_prefix = $this->class_prefix( $frm_settings );
100 $captcha_class = $this->captcha_class( $frm_settings );
101 $captcha_size = $this->captcha_size( $frm_settings );
102 $allow_mutiple = $frm_settings->re_multi;
103
104 if ( $frm_settings->active_captcha === 'recaptcha' ) {
105 $site_key = $frm_settings->pubkey;
106 $recaptcha_options = '" data-size="' . esc_attr( $captcha_size ) . '" data-theme="' . esc_attr( $this->field['captcha_theme'] ) . '"';
107 } else {
108 $site_key = $frm_settings->hcaptcha_pubkey;
109 }
110
111 $html = '<div id="' . esc_attr( $args['html_id'] ) . '" class="' . esc_attr( $class_prefix ) . $captcha_class . '" data-sitekey="' . esc_attr( $site_key ) . '"';
112 $html .= ! empty( $recaptcha_options ) ? $recaptcha_options : '';
113 if ( $captcha_size === 'invisible' && ! $allow_mutiple ) {
114 $html .= ' data-callback="frmAfterRecaptcha"';
115 }
116 $html .= '></div>';
117
118 return $html;
119 }
120
121 protected function load_field_scripts( $args ) {
122 $api_js_url = $this->api_url();
123
124 wp_register_script( 'captcha-api', $api_js_url, array( 'formidable' ), '3', true );
125 wp_enqueue_script( 'captcha-api' );
126 }
127
128 protected function api_url() {
129 $frm_settings = FrmAppHelper::get_settings();
130 if ( $frm_settings->active_captcha === 'recaptcha' ) {
131 return $this->recaptcha_api_url( $frm_settings );
132 }
133
134 return $this->hcaptcha_api_url();
135 }
136
137 protected function recaptcha_api_url( $frm_settings ) {
138 $api_js_url = 'https://www.google.com/recaptcha/api.js?';
139
140 $allow_mutiple = $frm_settings->re_multi;
141 if ( $allow_mutiple ) {
142 $api_js_url .= '&onload=frmRecaptcha&render=explicit';
143 }
144
145 $lang = apply_filters( 'frm_recaptcha_lang', $frm_settings->re_lang, $this->field );
146 if ( ! empty( $lang ) ) {
147 $api_js_url .= '&hl=' . $lang;
148 }
149
150 $api_js_url = apply_filters( 'frm_recaptcha_js_url', $api_js_url );
151
152 return $api_js_url;
153 }
154
155 protected function hcaptcha_api_url() {
156 $api_js_url = 'https://js.hcaptcha.com/1/api.js';
157
158 /**
159 * Allows updating hcaptcha js api url.
160 *
161 * @since x.x
162 *
163 * @param string $api_js_url
164 */
165 $api_js_url = apply_filters( 'frm_hcaptcha_js_url', $api_js_url );
166
167 return $api_js_url;
168 }
169
170 protected function class_prefix( $frm_settings ) {
171 if ( $this->allow_multiple( $frm_settings ) && $frm_settings->active_captcha === 'recaptcha' ) {
172 $class_prefix = 'frm-';
173 } else {
174 $class_prefix = '';
175 }
176
177 return $class_prefix;
178 }
179
180 protected function captcha_class( $frm_settings ) {
181 return $frm_settings->active_captcha === 'recaptcha' ? 'g-recaptcha' : 'h-captcha';
182 }
183
184 protected function allow_multiple( $frm_settings ) {
185 return $frm_settings->re_multi;
186 }
187
188 /**
189 * @return string
190 */
191 protected function captcha_size( $frm_settings ) {
192 if ( in_array( $frm_settings->re_type, array( 'invisible', 'v3' ), true ) ) {
193 return 'invisible';
194 }
195 // for reverse compatibility
196 return $this->field['captcha_size'] === 'default' ? 'normal' : $this->field['captcha_size'];
197 }
198
199 /**
200 * @since 4.07
201 * @param array $args
202 * @return array
203 */
204 protected function validate_against_api( $args ) {
205 $errors = array();
206 $frm_settings = FrmAppHelper::get_settings();
207 $resp = $this->send_api_check( $frm_settings );
208 $response = json_decode( wp_remote_retrieve_body( $resp ), true );
209
210 if ( is_wp_error( $resp ) ) {
211 $error_string = $resp->get_error_message();
212 $errors[ 'field' . $args['id'] ] = __( 'There was a problem verifying your captcha', 'formidable' );
213 $errors[ 'field' . $args['id'] ] .= ' ' . $error_string;
214 return $errors;
215 }
216
217 if ( ! is_array( $response ) ) {
218 return $errors;
219 }
220
221 if ( $frm_settings->active_captcha === 'recaptcha' ) {
222 if ( 'v3' === $frm_settings->re_type && array_key_exists( 'score', $response ) ) {
223 $threshold = floatval( $frm_settings->re_threshold );
224 $score = floatval( $response['score'] );
225
226 $this->set_score( $score );
227
228 if ( $score < $threshold ) {
229 $response['success'] = false;
230 }
231 }
232 }
233
234 if ( isset( $response['success'] ) && ! $response['success'] ) {
235 // What happens when the CAPTCHA was entered incorrectly
236 $invalid_message = FrmField::get_option( $this->field, 'invalid' );
237 if ( $invalid_message === __( 'The reCAPTCHA was not entered correctly', 'formidable' ) ) {
238 $invalid_message = '';
239 }
240 $errors[ 'field' . $args['id'] ] = ( $invalid_message === '' ? $frm_settings->re_msg : $invalid_message );
241 }
242
243 return $errors;
244 }
245
246 /**
247 * @param float $score
248 * @return void
249 */
250 private function set_score( $score ) {
251 global $frm_vars;
252 if ( ! isset( $frm_vars['captcha_scores'] ) ) {
253 $frm_vars['captcha_scores'] = array();
254 }
255 $form_id = is_object( $this->field ) ? $this->field->form_id : $this->field['form_id'];
256 if ( ! isset( $frm_vars['captcha_scores'][ $form_id ] ) ) {
257 $frm_vars['captcha_scores'][ $form_id ] = $score;
258 }
259 }
260
261 /**
262 * @param array $args
263 * @return array
264 */
265 public function validate( $args ) {
266 if ( ! $this->should_validate() ) {
267 return array();
268 }
269
270 // phpcs:ignore WordPress.Security.NonceVerification.Missing
271 if ( ! isset( $_POST['g-recaptcha-response'] ) && ! isset( $_POST['h-captcha-response'] ) ) {
272 // There was no captcha submitted.
273 return array( 'field' . $args['id'] => __( 'The captcha is missing from this form', 'formidable' ) );
274 }
275
276 return $this->validate_against_api( $args );
277 }
278
279 /**
280 * @since 4.07
281 * @return bool
282 */
283 public static function should_show_captcha() {
284 $frm_settings = FrmAppHelper::get_settings();
285 if ( $frm_settings->active_captcha === 'recaptcha' ) {
286 return ! empty( $frm_settings->pubkey );
287 }
288
289 return ! empty( $frm_settings->hcaptcha_pubkey );
290 }
291
292 protected function should_validate() {
293 $is_hidden_field = apply_filters( 'frm_is_field_hidden', false, $this->field, wp_unslash( $_POST ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
294 if ( FrmAppHelper::is_admin() || $is_hidden_field ) {
295 return false;
296 }
297
298 // don't require the captcha if it shouldn't be shown
299 return self::should_show_captcha();
300 }
301
302 protected function send_api_check( $frm_settings ) {
303 $captcha_settings = new FrmFieldCaptchaSettings( $frm_settings );
304
305 $arg_array = array(
306 'body' => array(
307 'secret' => $captcha_settings->secret,
308 'response' => FrmAppHelper::get_param( $captcha_settings->token_field, '', 'post', 'sanitize_text_field' ),
309 'remoteip' => FrmAppHelper::get_ip_address(),
310 ),
311 );
312
313 return wp_remote_post( $captcha_settings->endpoint, $arg_array );
314 }
315
316 /**
317 * Updates field name in page builder to the currently activated captcha if it is set to the default.
318 *
319 * @since x.x
320 *
321 * @param array $values
322 *
323 * @return array $values
324 */
325 public static function update_field_name( $values ) {
326 if ( $values['type'] === 'captcha' ) {
327 $name = $values['name'];
328 if ( in_array( $name, array( __( 'reCAPTCHA', 'formidable' ), __( 'hCaptcha', 'formidable' ) ), true ) ) {
329 $values['name'] = __( 'CAPTCHA', 'formidable' );
330 }
331 }
332
333 return $values;
334 }
335 }
336