| @@ -27,10 +27,9 @@ | ||
| 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' ) ); | |
| 31 | + add_action( 'init', array( $this, 'listen_for_submit' ) ); | |
| 33 | 32 | add_action( 'init', array( $this, 'register_assets' ) ); |
| 34 | 33 | add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_assets' ) ); |
| 35 | 34 | add_action( 'parse_request', array( $this, 'listen_for_preview' ) ); |
| 36 | 35 | add_filter( 'hf_form_markup', 'hf_template' ); |
| @@ -224,35 +223,19 @@ | ||
| 224 | 223 | return $data; |
| 225 | 224 | } |
| 226 | 225 | |
| 227 | 226 | 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 | - } | |
| 227 | + // only respond to AJAX requests with _hf_form_id set. | |
| 228 | + if ( empty( $_POST['_hf_form_id'] ) | |
| 229 | + || empty( $_SERVER['HTTP_X_REQUESTED_WITH'] ) | |
| 230 | + || strtolower( $_SERVER['HTTP_X_REQUESTED_WITH'] ) !== strtolower( 'XMLHttpRequest' ) ) { | |
| 231 | + return; | |
| 232 | + } | |
| 245 | 233 | |
| 246 | 234 | $data = $this->get_request_data(); |
| 247 | 235 | $form_id = (int) $data['_hf_form_id']; |
| 248 | - try { | |
| 249 | - $form = hf_get_form( $form_id ); | |
| 250 | - } catch ( \Exception $e ) { | |
| 251 | - return; | |
| 252 | - } | |
| 236 | + $form = hf_get_form( $form_id ); | |
| 253 | 237 | $error_code = $this->validate_form( $form, $data ); |
| 254 | - $submission = null; | |
| 255 | 238 | |
| 256 | 239 | if ( empty( $error_code ) ) { |
| 257 | 240 | /** |
| 258 | 241 | * Filters the field names that should be ignored on the Submission object. |
| @@ -285,9 +268,9 @@ | ||
| 285 | 268 | $submission->form_id = $form_id; |
| 286 | 269 | $submission->data = $data; |
| 287 | 270 | $submission->ip_address = ! empty( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( $_SERVER['REMOTE_ADDR'] ) : ''; |
| 288 | 271 | $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'] ) : ''; | |
| 272 | + $submission->referer_url = ! empty( $_SERVER['HTTP_REFERER'] ) ? sanitize_text_field( $_SERVER['HTTP_REFERER'] ) : ''; | |
| 290 | 273 | $submission->submitted_at = gmdate( 'Y-m-d H:i:s' ); |
| 291 | 274 | |
| 292 | 275 | // save submission object so that other form processor have an insert ID to work with (eg file upload) |
| 293 | 276 | if ( $form->settings['save_submissions'] ) { |
| @@ -344,10 +327,26 @@ | ||
| 344 | 327 | do_action( 'hf_form_error', $error_code, $form, $data ); |
| 345 | 328 | } |
| 346 | 329 | |
| 347 | 330 | // 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 ); | |
| 331 | + add_action( | |
| 332 | + 'wp_loaded', | |
| 333 | + function() use ( $error_code, $form, $data ) { | |
| 334 | + $response = $this->get_response_for_error_code( $error_code, $form, $data ); | |
| 335 | + | |
| 336 | + // clear output, some plugin or hooked code might have thrown errors by now. | |
| 337 | + if ( ob_get_level() > 0 ) { | |
| 338 | + ob_end_clean(); | |
| 339 | + } | |
| 340 | + | |
| 341 | + send_origin_headers(); | |
| 342 | + send_nosniff_header(); | |
| 343 | + nocache_headers(); | |
| 344 | + | |
| 345 | + wp_send_json( $response, 200 ); | |
| 346 | + exit; | |
| 347 | + } | |
| 348 | + ); | |
| 350 | 349 | } |
| 351 | 350 | |
| 352 | 351 | public function listen_for_preview() { |
| 353 | 352 | if ( empty( $_GET['hf_preview_form'] ) || ! current_user_can( 'edit_forms' ) ) { |
| @@ -377,9 +376,9 @@ | ||
| 377 | 376 | } |
| 378 | 377 | ); |
| 379 | 378 | } |
| 380 | 379 | |
| 381 | - private function get_response_for_error_code( $error_code, Form $form, $data = array(), ?Submission $submission = null ) { | |
| 380 | + private function get_response_for_error_code( $error_code, Form $form, $data = array() ) { | |
| 382 | 381 | // return success response for empty error code string or spam (to trick bots) |
| 383 | 382 | if ( $error_code === '' || $error_code === 'spam' ) { |
| 384 | 383 | $response = array( |
| 385 | 384 | 'message' => array( |
| @@ -388,16 +387,10 @@ | ||
| 388 | 387 | ), |
| 389 | 388 | 'hide_form' => (bool) $form->settings['hide_after_success'], |
| 390 | 389 | ); |
| 391 | 390 | |
| 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 | - } | |
| 391 | + if ( ! empty( $form->settings['redirect_url'] ) ) { | |
| 392 | + $response['redirect_url'] = hf_replace_data_variables( $form->settings['redirect_url'], $data, 'urlencode' ); | |
| 400 | 393 | } |
| 401 | 394 | |
| 402 | 395 | return apply_filters( 'hf_form_response', $response, $form, $data ); |
| 403 | 396 | } |
| @@ -422,9 +415,9 @@ | ||
| 422 | 415 | if ( empty( $attributes['slug'] ) && empty( $attributes['id'] ) ) { |
| 423 | 416 | return ''; |
| 424 | 417 | } |
| 425 | 418 | |
| 426 | - $slug_or_id = esc_attr( empty( $attributes['id'] ) ? $attributes['slug'] : $attributes['id'] ); | |
| 419 | + $slug_or_id = empty( $attributes['id'] ) ? $attributes['slug'] : $attributes['id']; | |
| 427 | 420 | try { |
| 428 | 421 | $form = hf_get_form( $slug_or_id ); |
| 429 | 422 | } catch ( \Exception $e ) { |
| 430 | 423 | if ( ! current_user_can( 'manage_options' ) ) { |
| @@ -430,9 +423,9 @@ | ||
| 430 | 423 | if ( ! current_user_can( 'manage_options' ) ) { |
| 431 | 424 | return $content; |
| 432 | 425 | } |
| 433 | 426 | |
| 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'] ) ) ); | |
| 427 | + return sprintf( '<p><strong>%s</strong> %s</p>', __( 'Error:', 'html-forms' ), sprintf( __( 'No form found with slug %s', 'html-forms' ), $attributes['slug'] ) ); | |
| 435 | 428 | } |
| 436 | 429 | |
| 437 | 430 | return $form . $content; |
| 438 | 431 | } |