PluginProbe
HTML Forms – Simple WordPress Forms Plugin / 1.3.21
HTML Forms – Simple WordPress Forms Plugin v1.3.21
trunk 1.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.1 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.2.0 1.3.0 1.3.1 1.3.10 1.3.11 1.3.12 1.3.13 1.3.14 1.3.15 1.3.16 1.3.17 All 66 releases
← All changes | src/class-forms.php +55 -76 trunk1.3.21 View file →
@@ -27,13 +27,11 @@
27 27 }
28 28
29 29 public function hook() {
30 30 add_action( 'init', array( $this, 'register' ) );
31 - add_action( 'wp_ajax_hf_form_submit', array( $this, 'listen_for_submit' ) );
32 - add_action( 'wp_ajax_nopriv_hf_form_submit', array( $this, 'listen_for_submit' ) );
33 - add_action( 'init', array( $this, 'register_assets' ) );
34 - add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_assets' ) );
31 + add_action( 'init', array( $this, 'listen_for_submit' ) );
35 32 add_action( 'parse_request', array( $this, 'listen_for_preview' ) );
33 + add_action( 'wp_enqueue_scripts', array( $this, 'assets' ) );
36 34 add_filter( 'hf_form_markup', 'hf_template' );
37 35 }
38 36
39 37 public function register() {
@@ -61,41 +59,27 @@
61 59
62 60 add_shortcode( 'hf_form', array( $this, 'shortcode' ) );
63 61 }
64 62
65 - public function register_assets() {
63 + public function assets() {
64 + $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
66 65 $assets_url = plugins_url( 'assets/', $this->plugin_file );
67 66
68 - wp_register_script( 'html-forms', $assets_url . 'js/public.js', array(), HTML_FORMS_VERSION, true );
67 + wp_register_script( 'html-forms', $assets_url . "js/public{$suffix}.js", array(), HTML_FORMS_VERSION, true );
69 68 wp_localize_script(
70 69 'html-forms',
71 70 'hf_js_vars',
72 71 array(
73 - 'ajax_url' => admin_url( 'admin-ajax.php?action=hf_form_submit' ),
72 + 'ajax_url' => admin_url( 'admin-ajax.php' ),
74 73 )
75 74 );
76 75
77 - wp_register_style( 'html-forms', $assets_url . 'css/forms.css', array(), HTML_FORMS_VERSION );
78 - add_filter( 'script_loader_tag', array( $this, 'add_defer_attribute' ), 10, 2 );
79 - }
80 -
81 - public function enqueue_assets() {
82 76 if ( $this->settings['load_stylesheet'] ) {
83 - wp_enqueue_style( 'html-forms' );
77 + wp_enqueue_style( 'html-forms', $assets_url . "css/forms{$suffix}.css", array(), HTML_FORMS_VERSION );
84 78 }
85 79 }
86 80
87 81 /**
88 - * Adds defer attribute to our <script> element
89 - */
90 - public function add_defer_attribute( $tag, $handle ) {
91 - if ( $handle !== 'html-forms' ) {
92 - return $tag;
93 - }
94 -
95 - return str_replace( ' src=', ' defer src=', $tag );
96 - }
97 - /**
98 82 * @param Form $form
99 83 * @param array $data
100 84 * @return string
101 85 */
@@ -161,13 +145,13 @@
161 145 return '';
162 146 }
163 147
164 148 /**
165 - * Sanitize array with values before saving. Can be called recursively.
166 - *
167 - * @param mixed $value
168 - * @return mixed
169 - */
149 + * Sanitize array with values before saving. Can be called recursively.
150 + *
151 + * @param mixed $value
152 + * @return mixed
153 + */
170 154 public function sanitize( $value ) {
171 155 if ( is_string( $value ) ) {
172 156 // do nothing if empty string
173 157 if ( $value === '' ) {
@@ -205,10 +189,10 @@
205 189 return $value;
206 190 }
207 191
208 192 /**
209 - * @return array
210 - */
193 + * @return array
194 + */
211 195 public function get_request_data() {
212 196 $data = $_POST;
213 197
214 198 if ( ! empty( $_FILES ) ) {
@@ -224,43 +208,28 @@
224 208 return $data;
225 209 }
226 210
227 211 public function listen_for_submit() {
228 - // Check nonce only if enabled in settings
229 - $nonce_check_failed = false;
230 - if ( $this->settings['enable_nonce'] ) {
231 - $nonce_check_failed = ! check_ajax_referer( 'html_forms_submit', '_wpnonce', false );
232 - }
233 -
234 - if ( $nonce_check_failed || empty( $_POST['_hf_form_id'] ) ) {
235 - wp_send_json(
236 - array(
237 - 'message' => array(
238 - 'type' => 'warning',
239 - 'text' => __( 'Something went wrong. Please reload the page and try again.', 'html-forms' ),
240 - ),
241 - 'error' => 'error',
242 - ),
243 - 200 );
244 - }
245 212
213 + // only respond to AJAX requests with _hf_form_id set.
214 + if ( empty( $_POST['_hf_form_id'] )
215 + || empty( $_SERVER['HTTP_X_REQUESTED_WITH'] )
216 + || strtolower( $_SERVER['HTTP_X_REQUESTED_WITH'] ) !== strtolower( 'XMLHttpRequest' ) ) {
217 + return;
218 + }
219 +
246 220 $data = $this->get_request_data();
247 221 $form_id = (int) $data['_hf_form_id'];
248 - try {
249 - $form = hf_get_form( $form_id );
250 - } catch ( \Exception $e ) {
251 - return;
252 - }
222 + $form = hf_get_form( $form_id );
253 223 $error_code = $this->validate_form( $form, $data );
254 - $submission = null;
255 224
256 225 if ( empty( $error_code ) ) {
257 226 /**
258 - * Filters the field names that should be ignored on the Submission object.
259 - * Fields starting with an underscore (_) are ignored by default.
260 - *
261 - * @param array $names
262 - */
227 + * Filters the field names that should be ignored on the Submission object.
228 + * Fields starting with an underscore (_) are ignored by default.
229 + *
230 + * @param array $names
231 + */
263 232 $ignored_field_names = apply_filters( 'hf_ignored_field_names', array() );
264 233
265 234 // filter out ignored field names
266 235 foreach ( $data as $key => $value ) {
@@ -285,24 +254,24 @@
285 254 $submission->form_id = $form_id;
286 255 $submission->data = $data;
287 256 $submission->ip_address = ! empty( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( $_SERVER['REMOTE_ADDR'] ) : '';
288 257 $submission->user_agent = ! empty( $_SERVER['HTTP_USER_AGENT'] ) ? sanitize_text_field( $_SERVER['HTTP_USER_AGENT'] ) : '';
289 - $submission->referer_url = ! empty( $_SERVER['HTTP_REFERER'] ) ? sanitize_url( $_SERVER['HTTP_REFERER'] ) : '';
258 + $submission->referer_url = ! empty( $_SERVER['HTTP_REFERER'] ) ? sanitize_text_field( $_SERVER['HTTP_REFERER'] ) : '';
290 259 $submission->submitted_at = gmdate( 'Y-m-d H:i:s' );
291 260
292 261 // save submission object so that other form processor have an insert ID to work with (eg file upload)
293 262 if ( $form->settings['save_submissions'] ) {
294 - $submission->save();
263 + $submission->save();
295 264 }
296 265
297 266 /**
298 - * General purpose hook that runs before all form actions, so we can still modify the submission object that is passed to actions.
299 - */
267 + * General purpose hook that runs before all form actions, so we can still modify the submission object that is passed to actions.
268 + */
300 269 do_action( 'hf_process_form', $form, $submission );
301 270
302 271 // re-save submission object for convenience in form processors hooked into hf_process_form
303 272 if ( $form->settings['save_submissions'] ) {
304 - $submission->save();
273 + $submission->save();
305 274 }
306 275
307 276 // process form actions
308 277 if ( isset( $form->settings['actions'] ) ) {
@@ -344,10 +313,26 @@
344 313 do_action( 'hf_form_error', $error_code, $form, $data );
345 314 }
346 315
347 316 // Delay response until "wp_loaded" hook to give other plugins a chance to process stuff.
348 - $response = $this->get_response_for_error_code( $error_code, $form, $data, $submission );
349 - wp_send_json( $response, 200 );
317 + add_action(
318 + 'wp_loaded',
319 + function() use ( $error_code, $form, $data ) {
320 + $response = $this->get_response_for_error_code( $error_code, $form, $data );
321 +
322 + // clear output, some plugin or hooked code might have thrown errors by now.
323 + if ( ob_get_level() > 0 ) {
324 + ob_end_clean();
325 + }
326 +
327 + send_origin_headers();
328 + send_nosniff_header();
329 + nocache_headers();
330 +
331 + wp_send_json( $response, 200 );
332 + exit;
333 + }
334 + );
350 335 }
351 336
352 337 public function listen_for_preview() {
353 338 if ( empty( $_GET['hf_preview_form'] ) || ! current_user_can( 'edit_forms' ) ) {
@@ -377,9 +362,9 @@
377 362 }
378 363 );
379 364 }
380 365
381 - private function get_response_for_error_code( $error_code, Form $form, $data = array(), ?Submission $submission = null ) {
366 + private function get_response_for_error_code( $error_code, Form $form, $data = array() ) {
382 367 // return success response for empty error code string or spam (to trick bots)
383 368 if ( $error_code === '' || $error_code === 'spam' ) {
384 369 $response = array(
385 370 'message' => array(
@@ -388,16 +373,10 @@
388 373 ),
389 374 'hide_form' => (bool) $form->settings['hide_after_success'],
390 375 );
391 376
392 - if ( ! empty( $form->settings['redirect_url'] ) && $submission !== null ) {
393 - $url = hf_replace_data_variables( $form->settings['redirect_url'], $submission, 'urlencode' );
394 -
395 - // Validate the scheme again to prevent javascript: XSS
396 - $scheme = wp_parse_url( $url, PHP_URL_SCHEME );
397 - if ( $scheme === null || in_array( strtolower( $scheme ), array( 'http', 'https' ), true ) ) {
398 - $response['redirect_url'] = $url;
399 - }
377 + if ( ! empty( $form->settings['redirect_url'] ) ) {
378 + $response['redirect_url'] = hf_replace_data_variables( $form->settings['redirect_url'], $data, 'urlencode' );
400 379 }
401 380
402 381 return apply_filters( 'hf_form_response', $response, $form, $data );
403 382 }
@@ -422,9 +401,9 @@
422 401 if ( empty( $attributes['slug'] ) && empty( $attributes['id'] ) ) {
423 402 return '';
424 403 }
425 404
426 - $slug_or_id = esc_attr( empty( $attributes['id'] ) ? $attributes['slug'] : $attributes['id'] );
405 + $slug_or_id = empty( $attributes['id'] ) ? $attributes['slug'] : $attributes['id'];
427 406 try {
428 407 $form = hf_get_form( $slug_or_id );
429 408 } catch ( \Exception $e ) {
430 409 if ( ! current_user_can( 'manage_options' ) ) {
@@ -430,9 +409,9 @@
430 409 if ( ! current_user_can( 'manage_options' ) ) {
431 410 return $content;
432 411 }
433 412
434 - return sprintf( '<p><strong>%s</strong> %s</p>', __( 'Error:', 'html-forms' ), sprintf( __( 'No form found with slug %s', 'html-forms' ), esc_attr( $attributes['slug'] ) ) );
413 + return sprintf( '<p><strong>%s</strong> %s</p>', __( 'Error:', 'html-forms' ), sprintf( __( 'No form found with slug %s', 'html-forms' ), $attributes['slug'] ) );
435 414 }
436 415
437 416 return $form . $content;
438 417 }