: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
// Hash created 30-60 minutes ago.
$expected_2 = $this->create_posted_data_hash( $tick - 1 );
if ( hash_equals( $expected_2, $hash ) ) {
* Retrieves the remote IP address of this submission.
private function get_remote_ip_addr() {
if ( isset( $_SERVER['REMOTE_ADDR'] )
and WP_Http::is_ip_address( $_SERVER['REMOTE_ADDR'] ) ) {
$ip_addr = $_SERVER['REMOTE_ADDR'];
return apply_filters( 'wpcf7_remote_ip_addr', $ip_addr );
* Retrieves the request URL of this submission.
private function get_request_url() {
$home_url = untrailingslashit( home_url() );
if ( self::is_restful() ) {
$referer = trim( $_SERVER['HTTP_REFERER'] ?? '' );
and 0 === strpos( $referer, $home_url ) ) {
return sanitize_url( $referer );
$url = preg_replace( '%(?<!:|/)/.*$%', '', $home_url )
. wpcf7_get_request_uri();
* Runs user input validation.
* @return bool True if no invalid field is found.
private function validate() {
if ( $this->invalid_fields ) {
$result = new WPCF7_Validation();
$this->contact_form->validate_schema(
$tags = $this->contact_form->scan_form_tags( array(
'feature' => '! file-uploading',
foreach ( $tags as $tag ) {
$result = apply_filters( "wpcf7_validate_{$type}", $result, $tag );
$result = apply_filters( 'wpcf7_validate', $result, $tags );
$this->invalid_fields = $result->get_invalid_fields();
return $result->is_valid();
* Returns true if user consent is obtained.
private function accepted() {
return apply_filters( 'wpcf7_acceptance', true, $this );
* Adds user consent data to this submission.
* @param string $name Field name.
* @param string $conditions Conditions of consent.
public function add_consent( $name, $conditions ) {
$this->consent[$name] = $conditions;
* Collects user consent data.
* @return array User consent data.
public function collect_consent() {
return (array) $this->consent;
* Executes spam protections.
* @return bool True if spam captured.
private function spam() {
$skip_spam_check = apply_filters( 'wpcf7_skip_spam_check',
if ( $skip_spam_check ) {
if ( $this->contact_form->is_true( 'subscribers_only' )
and current_user_can( 'wpcf7_submit', $this->contact_form->id() ) ) {
$user_agent = (string) $this->get_meta( 'user_agent' );
if ( strlen( $user_agent ) < 2 ) {
$this->add_spam_log( array(
'reason' => __( "User-Agent string is unnaturally short.", 'contact-form-7' ),
if ( ! $this->verify_nonce() ) {
$this->add_spam_log( array(
'reason' => __( "Submitted nonce is invalid.", 'contact-form-7' ),
return apply_filters( 'wpcf7_spam', $spam, $this );
* @link https://contactform7.com/2019/05/31/why-is-this-message-marked-spam/
public function add_spam_log( $data = '' ) {
$data = wp_parse_args( $data, array(
$this->spam_log[] = $data;
* Retrieves the spam logging data.
* @return array Spam logging data.
public function get_spam_log() {
* Verifies that a correct security nonce was used.
private function verify_nonce() {
if ( ! $this->contact_form->nonce_is_active() or ! is_user_logged_in() ) {
$nonce = $_POST['_wpnonce'] ?? '';
return wpcf7_verify_nonce( $nonce );
* Function called just before sending email.
private function before_send_mail() {
do_action_ref_array( 'wpcf7_before_send_mail', array(
* Sends emails based on user input values and contact form email templates.
private function mail() {
$contact_form = $this->contact_form;
$skip_mail = apply_filters( 'wpcf7_skip_mail',
$this->skip_mail, $contact_form
$result = WPCF7_Mail::send( $contact_form->prop( 'mail' ), 'mail' );
$additional_mail = array();
if ( $mail_2 = $contact_form->prop( 'mail_2' )
and $mail_2['active'] ) {
$additional_mail['mail_2'] = $mail_2;
$additional_mail = apply_filters( 'wpcf7_additional_mail',
$additional_mail, $contact_form
foreach ( $additional_mail as $name => $template ) {
WPCF7_Mail::send( $template, $name );
* Retrieves files uploaded through this submission.
public function uploaded_files() {
return $this->uploaded_files;
* Adds a file to the uploaded files array.
* @param string $name Field name.
* @param string|array $file_path File path or array of file paths.
private function add_uploaded_file( $name, $file_path ) {
if ( ! wpcf7_is_name( $name ) ) {
$paths = (array) $file_path;
$uploaded_files = array();
foreach ( $paths as $path ) {
if ( @is_file( $path ) and @is_readable( $path ) ) {
$uploaded_files[] = $path;
$hash_strings[] = md5_file( $path );
$this->uploaded_files[$name] = $uploaded_files;
if ( empty( $this->posted_data[$name] ) ) {
$this->posted_data[$name] = implode( ' ', $hash_strings );
* Removes uploaded files.
private function remove_uploaded_files() {
foreach ( (array) $this->uploaded_files as $file_path ) {
$paths = (array) $file_path;
foreach ( $paths as $path ) {
if ( $dir = dirname( $path )
and false !== ( $files = scandir( $dir ) )
and ! array_diff( $files, array( '.', '..' ) ) ) {
// remove parent dir if it's empty.
* Moves uploaded files to the tmp directory and validates them.
* @return bool True if no invalid file is found.
private function unship_uploaded_files() {
$result = new WPCF7_Validation();
$tags = $this->contact_form->scan_form_tags( array(
'feature' => 'file-uploading',
foreach ( $tags as $tag ) {
if ( empty( $_FILES[$tag->name] ) ) {
$file = $_FILES[$tag->name];
'required' => $tag->is_required(),
'filetypes' => $tag->get_option( 'filetypes' ),
'limit' => $tag->get_limit_option(),
'schema' => $this->contact_form->get_schema(),
$new_files = wpcf7_unship_uploaded_file( $file, $options );
if ( is_wp_error( $new_files ) ) {
$result->invalidate( $tag, $new_files );
$this->add_uploaded_file( $tag->name, $new_files );
"wpcf7_validate_{$tag->type}",
'uploaded_files' => $new_files,
$this->invalid_fields = $result->get_invalid_fields();
return $result->is_valid();
* Adds extra email attachment files that are independent from form fields.
* @param string|array $file_path A file path or an array of file paths.
* @param string $template Optional. The name of the template to which
* the files are attached.
* @return bool True if it succeeds to attach a file at least,
public function add_extra_attachments( $file_path, $template = 'mail' ) {
if ( ! did_action( 'wpcf7_before_send_mail' ) ) {
$extra_attachments = array();
foreach ( (array) $file_path as $path ) {
$path = path_join( WP_CONTENT_DIR, $path );
if ( file_exists( $path ) ) {
$extra_attachments[] = $path;
if ( empty( $extra_attachments ) ) {
if ( ! isset( $this->extra_attachments[$template] ) ) {
$this->extra_attachments[$template] = array();
$this->extra_attachments[$template] = array_merge(
$this->extra_attachments[$template],
* Returns extra email attachment files.
* @param string $template An email template name.
* @return array Array of file paths.
public function extra_attachments( $template ) {
if ( isset( $this->extra_attachments[$template] ) ) {
return (array) $this->extra_attachments[$template];