This commit is contained in:
Rachit Bhargava
2024-01-10 11:53:33 -05:00
parent 83d223b0df
commit 054b4fffc9
16481 changed files with 0 additions and 3473867 deletions

View File

@@ -1,86 +0,0 @@
<?php
add_action(
'init',
'wpcf7_init_block_editor_assets',
10, 0
);
function wpcf7_init_block_editor_assets() {
$assets = array();
$asset_file = wpcf7_plugin_path(
'includes/block-editor/index.asset.php'
);
if ( file_exists( $asset_file ) ) {
$assets = include( $asset_file );
}
$assets = wp_parse_args( $assets, array(
'dependencies' => array(
'wp-api-fetch',
'wp-block-editor',
'wp-blocks',
'wp-components',
'wp-element',
'wp-i18n',
'wp-url',
),
'version' => WPCF7_VERSION,
) );
wp_register_script(
'contact-form-7-block-editor',
wpcf7_plugin_url( 'includes/block-editor/index.js' ),
$assets['dependencies'],
$assets['version']
);
wp_set_script_translations(
'contact-form-7-block-editor',
'contact-form-7'
);
register_block_type(
wpcf7_plugin_path( 'includes/block-editor' ),
array(
'editor_script' => 'contact-form-7-block-editor',
)
);
}
add_action(
'enqueue_block_editor_assets',
'wpcf7_enqueue_block_editor_assets',
10, 0
);
function wpcf7_enqueue_block_editor_assets() {
$contact_forms = array_map(
static function ( $contact_form ) {
return array(
'id' => $contact_form->id(),
'hash' => $contact_form->hash(),
'slug' => $contact_form->name(),
'title' => $contact_form->title(),
'locale' => $contact_form->locale(),
);
},
WPCF7_ContactForm::find( array(
'posts_per_page' => 20,
'orderby' => 'modified',
'order' => 'DESC',
) )
);
wp_add_inline_script(
'contact-form-7-block-editor',
sprintf(
'window.wpcf7 = {contactForms:%s};',
wp_json_encode( $contact_forms )
),
'before'
);
}

View File

@@ -1,38 +0,0 @@
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 2,
"name": "contact-form-7/contact-form-selector",
"title": "Contact Form 7",
"category": "widgets",
"description": "Insert a contact form you have created with Contact Form 7.",
"keywords": [ "form" ],
"textdomain": "contact-form-7",
"attributes": {
"id": {
"type": "integer"
},
"hash": {
"type": "string"
},
"title": {
"type": "string"
},
"htmlId": {
"type": "string"
},
"htmlName": {
"type": "string"
},
"htmlTitle": {
"type": "string"
},
"htmlClass": {
"type": "string"
},
"output": {
"enum": [ "form", "raw_form" ],
"default": "form"
}
},
"editorScript": "file:./index.js"
}

View File

@@ -1,15 +0,0 @@
<?php
return array(
'dependencies' => array(
'react',
'wp-api-fetch',
'wp-block-editor',
'wp-blocks',
'wp-components',
'wp-element',
'wp-i18n',
'wp-url',
),
'version' => WPCF7_VERSION,
);

File diff suppressed because one or more lines are too long

View File

@@ -1,26 +0,0 @@
<?php
add_filter( 'map_meta_cap', 'wpcf7_map_meta_cap', 10, 4 );
function wpcf7_map_meta_cap( $caps, $cap, $user_id, $args ) {
$meta_caps = array(
'wpcf7_edit_contact_form' => WPCF7_ADMIN_READ_WRITE_CAPABILITY,
'wpcf7_edit_contact_forms' => WPCF7_ADMIN_READ_WRITE_CAPABILITY,
'wpcf7_read_contact_form' => WPCF7_ADMIN_READ_CAPABILITY,
'wpcf7_read_contact_forms' => WPCF7_ADMIN_READ_CAPABILITY,
'wpcf7_delete_contact_form' => WPCF7_ADMIN_READ_WRITE_CAPABILITY,
'wpcf7_delete_contact_forms' => WPCF7_ADMIN_READ_WRITE_CAPABILITY,
'wpcf7_manage_integration' => 'manage_options',
'wpcf7_submit' => 'read',
);
$meta_caps = apply_filters( 'wpcf7_map_meta_cap', $meta_caps );
$caps = array_diff( $caps, array_keys( $meta_caps ) );
if ( isset( $meta_caps[$cap] ) ) {
$caps[] = $meta_caps[$cap];
}
return $caps;
}

View File

@@ -1,27 +0,0 @@
<?php
add_action(
'wpcf7_update_option',
'wpcf7_config_validator_update_option',
10, 3
);
/**
* Runs bulk validation after the reCAPTCHA integration option is updated.
*/
function wpcf7_config_validator_update_option( $name, $value, $old_option ) {
if ( 'recaptcha' === $name ) {
$contact_forms = WPCF7_ContactForm::find();
$options = array(
'include' => 'unsafe_email_without_protection',
);
foreach ( $contact_forms as $contact_form ) {
$config_validator = new WPCF7_ConfigValidator( $contact_form, $options );
$config_validator->restore();
$config_validator->validate();
$config_validator->save();
}
}
}

View File

@@ -1,28 +0,0 @@
<?php
trait WPCF7_ConfigValidator_AdditionalSettings {
/**
* Runs error detection for the additional settings section.
*/
public function validate_additional_settings() {
$section = 'additional_settings.body';
if ( $this->supports( 'deprecated_settings' ) ) {
$deprecated_settings_used =
$this->contact_form->additional_setting( 'on_sent_ok' ) ||
$this->contact_form->additional_setting( 'on_submit' );
if ( $deprecated_settings_used ) {
$this->add_error( $section, 'deprecated_settings',
array(
'message' => __( "Deprecated settings are used.", 'contact-form-7' ),
)
);
} else {
$this->remove_error( $section, 'deprecated_settings' );
}
}
}
}

View File

@@ -1,278 +0,0 @@
<?php
trait WPCF7_ConfigValidator_Form {
/**
* Runs error detection for the form section.
*/
public function validate_form() {
$section = 'form.body';
$form = $this->contact_form->prop( 'form' );
if ( $this->supports( 'multiple_controls_in_label' ) ) {
if ( $this->detect_multiple_controls_in_label( $section, $form ) ) {
$this->add_error( $section, 'multiple_controls_in_label',
array(
'message' => __( "Multiple form controls are in a single label element.", 'contact-form-7' ),
)
);
} else {
$this->remove_error( $section, 'multiple_controls_in_label' );
}
}
if ( $this->supports( 'unavailable_names' ) ) {
$ng_names = $this->detect_unavailable_names( $section, $form );
if ( $ng_names ) {
$this->add_error( $section, 'unavailable_names',
array(
'message' =>
/* translators: %names%: a list of form control names */
__( "Unavailable names (%names%) are used for form controls.", 'contact-form-7' ),
'params' => array( 'names' => implode( ', ', $ng_names ) ),
)
);
} else {
$this->remove_error( $section, 'unavailable_names' );
}
}
if ( $this->supports( 'unavailable_html_elements' ) ) {
if ( $this->detect_unavailable_html_elements( $section, $form ) ) {
$this->add_error( $section, 'unavailable_html_elements',
array(
'message' => __( "Unavailable HTML elements are used in the form template.", 'contact-form-7' ),
)
);
} else {
$this->remove_error( $section, 'unavailable_html_elements' );
}
}
if ( $this->supports( 'dots_in_names' ) ) {
if ( $this->detect_dots_in_names( $section, $form ) ) {
$this->add_error( $section, 'dots_in_names',
array(
'message' => __( "Dots are used in form-tag names.", 'contact-form-7' ),
)
);
} else {
$this->remove_error( $section, 'dots_in_names' );
}
}
if ( $this->supports( 'colons_in_names' ) ) {
if ( $this->detect_colons_in_names( $section, $form ) ) {
$this->add_error( $section, 'colons_in_names',
array(
'message' => __( "Colons are used in form-tag names.", 'contact-form-7' ),
)
);
} else {
$this->remove_error( $section, 'colons_in_names' );
}
}
if ( $this->supports( 'upload_filesize_overlimit' ) ) {
if ( $this->detect_upload_filesize_overlimit( $section, $form ) ) {
$this->add_error( $section, 'upload_filesize_overlimit',
array(
'message' => __( "Uploadable file size exceeds PHPs maximum acceptable size.", 'contact-form-7' ),
)
);
} else {
$this->remove_error( $section, 'upload_filesize_overlimit' );
}
}
}
/**
* Detects errors of multiple form controls in a single label.
*
* @link https://contactform7.com/configuration-errors/multiple-controls-in-label/
*/
public function detect_multiple_controls_in_label( $section, $content ) {
$pattern = '%<label(?:[ \t\n]+.*?)?>(.+?)</label>%s';
if ( preg_match_all( $pattern, $content, $matches ) ) {
$form_tags_manager = WPCF7_FormTagsManager::get_instance();
foreach ( $matches[1] as $insidelabel ) {
$tags = $form_tags_manager->scan( $insidelabel );
$fields_count = 0;
foreach ( $tags as $tag ) {
$is_multiple_controls_container = wpcf7_form_tag_supports(
$tag->type, 'multiple-controls-container'
);
$is_zero_controls_container = wpcf7_form_tag_supports(
$tag->type, 'zero-controls-container'
);
if ( $is_multiple_controls_container ) {
$fields_count += count( $tag->values );
if ( $tag->has_option( 'free_text' ) ) {
$fields_count += 1;
}
} elseif ( $is_zero_controls_container ) {
$fields_count += 0;
} elseif ( ! empty( $tag->name ) ) {
$fields_count += 1;
}
if ( 1 < $fields_count ) {
return true;
}
}
}
}
return false;
}
/**
* Detects errors of unavailable form-tag names.
*
* @link https://contactform7.com/configuration-errors/unavailable-names/
*/
public function detect_unavailable_names( $section, $content ) {
$public_query_vars = array( 'm', 'p', 'posts', 'w', 'cat',
'withcomments', 'withoutcomments', 's', 'search', 'exact', 'sentence',
'calendar', 'page', 'paged', 'more', 'tb', 'pb', 'author', 'order',
'orderby', 'year', 'monthnum', 'day', 'hour', 'minute', 'second',
'name', 'category_name', 'tag', 'feed', 'author_name', 'static',
'pagename', 'page_id', 'error', 'attachment', 'attachment_id',
'subpost', 'subpost_id', 'preview', 'robots', 'taxonomy', 'term',
'cpage', 'post_type', 'embed',
);
$form_tags_manager = WPCF7_FormTagsManager::get_instance();
$ng_named_tags = $form_tags_manager->filter( $content, array(
'name' => $public_query_vars,
) );
$ng_names = array();
foreach ( $ng_named_tags as $tag ) {
$ng_names[] = sprintf( '"%s"', $tag->name );
}
if ( $ng_names ) {
return array_unique( $ng_names );
}
return false;
}
/**
* Detects errors of unavailable HTML elements.
*
* @link https://contactform7.com/configuration-errors/unavailable-html-elements/
*/
public function detect_unavailable_html_elements( $section, $content ) {
$pattern = '%(?:<form[\s\t>]|</form>)%i';
if ( preg_match( $pattern, $content ) ) {
return true;
}
return false;
}
/**
* Detects errors of dots in form-tag names.
*
* @link https://contactform7.com/configuration-errors/dots-in-names/
*/
public function detect_dots_in_names( $section, $content ) {
$form_tags_manager = WPCF7_FormTagsManager::get_instance();
$tags = $form_tags_manager->filter( $content, array(
'feature' => 'name-attr',
) );
foreach ( $tags as $tag ) {
if ( str_contains( $tag->raw_name, '.' ) ) {
return true;
}
}
return false;
}
/**
* Detects errors of colons in form-tag names.
*
* @link https://contactform7.com/configuration-errors/colons-in-names/
*/
public function detect_colons_in_names( $section, $content ) {
$form_tags_manager = WPCF7_FormTagsManager::get_instance();
$tags = $form_tags_manager->filter( $content, array(
'feature' => 'name-attr',
) );
foreach ( $tags as $tag ) {
if ( str_contains( $tag->raw_name, ':' ) ) {
return true;
}
}
return false;
}
/**
* Detects errors of uploadable file size overlimit.
*
* @link https://contactform7.com/configuration-errors/upload-filesize-overlimit
*/
public function detect_upload_filesize_overlimit( $section, $content ) {
$upload_max_filesize = ini_get( 'upload_max_filesize' );
if ( ! $upload_max_filesize ) {
return false;
}
$upload_max_filesize = strtolower( $upload_max_filesize );
$upload_max_filesize = trim( $upload_max_filesize );
if ( ! preg_match( '/^(\d+)([kmg]?)$/', $upload_max_filesize, $matches ) ) {
return false;
}
if ( 'k' === $matches[2] ) {
$upload_max_filesize = (int) $matches[1] * KB_IN_BYTES;
} elseif ( 'm' === $matches[2] ) {
$upload_max_filesize = (int) $matches[1] * MB_IN_BYTES;
} elseif ( 'g' === $matches[2] ) {
$upload_max_filesize = (int) $matches[1] * GB_IN_BYTES;
} else {
$upload_max_filesize = (int) $matches[1];
}
$form_tags_manager = WPCF7_FormTagsManager::get_instance();
$tags = $form_tags_manager->filter( $content, array(
'basetype' => 'file',
) );
foreach ( $tags as $tag ) {
if ( $upload_max_filesize < $tag->get_limit_option() ) {
return true;
}
}
return false;
}
}

View File

@@ -1,603 +0,0 @@
<?php
trait WPCF7_ConfigValidator_Mail {
/**
* Replaces all mail-tags in the given content.
*/
public function replace_mail_tags( $content, $args = '' ) {
$args = wp_parse_args( $args, array(
'html' => false,
'callback' =>
array( $this, 'replace_mail_tags_with_minimum_input_callback' ),
) );
$content = new WPCF7_MailTaggedText( $content, $args );
return $content->replace_tags();
}
/**
* Callback function for WPCF7_MailTaggedText. Replaces mail-tags with
* the most conservative inputs.
*/
public function replace_mail_tags_with_minimum_input_callback( $matches ) {
// allow [[foo]] syntax for escaping a tag
if ( $matches[1] === '[' and $matches[4] === ']' ) {
return substr( $matches[0], 1, -1 );
}
$tag = $matches[0];
$tagname = $matches[2];
$values = $matches[3];
$mail_tag = new WPCF7_MailTag( $tag, $tagname, $values );
$field_name = $mail_tag->field_name();
$example_email = 'example@example.com';
$example_text = 'example';
$example_blank = '';
$form_tags = $this->contact_form->scan_form_tags(
array( 'name' => $field_name )
);
if ( $form_tags ) {
$form_tag = new WPCF7_FormTag( $form_tags[0] );
$is_required = $form_tag->is_required() || 'radio' === $form_tag->type;
if ( ! $is_required ) {
return $example_blank;
}
if ( wpcf7_form_tag_supports( $form_tag->type, 'selectable-values' ) ) {
if ( $form_tag->pipes instanceof WPCF7_Pipes ) {
if ( $mail_tag->get_option( 'do_not_heat' ) ) {
$before_pipes = $form_tag->pipes->collect_befores();
$last_item = array_pop( $before_pipes );
} else {
$after_pipes = $form_tag->pipes->collect_afters();
$last_item = array_pop( $after_pipes );
}
} else {
$last_item = array_pop( $form_tag->values );
}
if ( $last_item and wpcf7_is_mailbox_list( $last_item ) ) {
return $example_email;
} else {
return $example_text;
}
}
if ( 'email' === $form_tag->basetype ) {
return $example_email;
} else {
return $example_text;
}
} else { // maybe special mail tag
// for back-compat
$field_name = preg_replace( '/^wpcf7\./', '_', $field_name );
if ( '_site_admin_email' === $field_name ) {
return get_bloginfo( 'admin_email', 'raw' );
} elseif ( '_user_agent' === $field_name ) {
return $example_text;
} elseif ( '_user_email' === $field_name ) {
return $this->contact_form->is_true( 'subscribers_only' )
? $example_email
: $example_blank;
} elseif ( str_starts_with( $field_name, '_user_' ) ) {
return $this->contact_form->is_true( 'subscribers_only' )
? $example_text
: $example_blank;
} elseif ( str_starts_with( $field_name, '_' ) ) {
return str_ends_with( $field_name, '_email' )
? $example_email
: $example_text;
}
}
return $tag;
}
/**
* Runs error detection for the mail sections.
*/
public function validate_mail( $template = 'mail' ) {
if (
$this->contact_form->is_true( 'demo_mode' ) or
$this->contact_form->is_true( 'skip_mail' )
) {
return;
}
$components = (array) $this->contact_form->prop( $template );
if ( ! $components ) {
return;
}
if ( 'mail' !== $template and empty( $components['active'] ) ) {
return;
}
$components = wp_parse_args( $components, array(
'subject' => '',
'sender' => '',
'recipient' => '',
'additional_headers' => '',
'body' => '',
'attachments' => '',
) );
$this->validate_mail_subject(
$template,
$components['subject']
);
$this->validate_mail_sender(
$template,
$components['sender']
);
$this->validate_mail_recipient(
$template,
$components['recipient']
);
$this->validate_mail_additional_headers(
$template,
$components['additional_headers']
);
$this->validate_mail_body(
$template,
$components['body']
);
$this->validate_mail_attachments(
$template,
$components['attachments']
);
}
/**
* Runs error detection for the mail subject section.
*/
public function validate_mail_subject( $template, $content ) {
$section = sprintf( '%s.subject', $template );
if ( $this->supports( 'maybe_empty' ) ) {
if ( $this->detect_maybe_empty( $section, $content ) ) {
$this->add_error( $section, 'maybe_empty',
array(
'message' => __( "There is a possible empty field.", 'contact-form-7' ),
)
);
} else {
$this->remove_error( $section, 'maybe_empty' );
}
}
}
/**
* Runs error detection for the mail sender section.
*/
public function validate_mail_sender( $template, $content ) {
$section = sprintf( '%s.sender', $template );
if ( $this->supports( 'invalid_mailbox_syntax' ) ) {
if ( $this->detect_invalid_mailbox_syntax( $section, $content ) ) {
$this->add_error( $section, 'invalid_mailbox_syntax',
array(
'message' => __( "Invalid mailbox syntax is used.", 'contact-form-7' ),
)
);
} else {
$this->remove_error( $section, 'invalid_mailbox_syntax' );
}
}
if ( $this->supports( 'email_not_in_site_domain' ) ) {
$this->remove_error( $section, 'email_not_in_site_domain' );
if ( ! $this->has_error( $section, 'invalid_mailbox_syntax' ) ) {
$sender = $this->replace_mail_tags( $content );
$sender = wpcf7_strip_newline( $sender );
if ( ! wpcf7_is_email_in_site_domain( $sender ) ) {
$this->add_error( $section, 'email_not_in_site_domain',
array(
'message' => __( "Sender email address does not belong to the site domain.", 'contact-form-7' ),
)
);
}
}
}
}
/**
* Runs error detection for the mail recipient section.
*/
public function validate_mail_recipient( $template, $content ) {
$section = sprintf( '%s.recipient', $template );
if ( $this->supports( 'invalid_mailbox_syntax' ) ) {
if ( $this->detect_invalid_mailbox_syntax( $section, $content ) ) {
$this->add_error( $section, 'invalid_mailbox_syntax',
array(
'message' => __( "Invalid mailbox syntax is used.", 'contact-form-7' ),
)
);
} else {
$this->remove_error( $section, 'invalid_mailbox_syntax' );
}
}
if ( $this->supports( 'unsafe_email_without_protection' ) ) {
$this->remove_error( $section, 'unsafe_email_without_protection' );
if ( ! $this->has_error( $section, 'invalid_mailbox_syntax' ) ) {
if (
$this->detect_unsafe_email_without_protection( $section, $content )
) {
$this->add_error( $section, 'unsafe_email_without_protection',
array(
'message' => __( "Unsafe email config is used without sufficient protection.", 'contact-form-7' ),
)
);
}
}
}
}
/**
* Runs error detection for the mail additional headers section.
*/
public function validate_mail_additional_headers( $template, $content ) {
$section = sprintf( '%s.additional_headers', $template );
$invalid_mail_headers = array();
$invalid_mailbox_fields = array();
$unsafe_email_fields = array();
foreach ( explode( "\n", $content ) as $header ) {
$header = trim( $header );
if ( '' === $header ) {
continue;
}
$is_valid_header = preg_match(
'/^([0-9A-Za-z-]+):(.*)$/',
$header,
$matches
);
if ( ! $is_valid_header ) {
$invalid_mail_headers[] = $header;
continue;
}
$header_name = $matches[1];
$header_value = trim( $matches[2] );
if (
in_array(
strtolower( $header_name ), array( 'reply-to', 'cc', 'bcc' )
) and
'' !== $header_value and
$this->detect_invalid_mailbox_syntax( $section, $header_value )
) {
$invalid_mailbox_fields[] = $header_name;
continue;
}
if (
in_array( strtolower( $header_name ), array( 'cc', 'bcc' ) ) and
$this->detect_unsafe_email_without_protection( $section, $header_value )
) {
$unsafe_email_fields[] = $header_name;
}
}
if ( $this->supports( 'invalid_mail_header' ) ) {
if ( ! empty( $invalid_mail_headers ) ) {
$this->add_error( $section, 'invalid_mail_header',
array(
'message' => __( "There are invalid mail header fields.", 'contact-form-7' ),
)
);
} else {
$this->remove_error( $section, 'invalid_mail_header' );
}
}
if ( $this->supports( 'invalid_mailbox_syntax' ) ) {
if ( ! empty( $invalid_mailbox_fields ) ) {
foreach ( $invalid_mailbox_fields as $header_name ) {
$this->add_error( $section, 'invalid_mailbox_syntax',
array(
'message' => __( "Invalid mailbox syntax is used in the %name% field.", 'contact-form-7' ),
'params' => array( 'name' => $header_name ),
)
);
}
} else {
$this->remove_error( $section, 'invalid_mailbox_syntax' );
}
}
if ( $this->supports( 'unsafe_email_without_protection' ) ) {
if ( ! empty( $unsafe_email_fields ) ) {
$this->add_error( $section, 'unsafe_email_without_protection',
array(
'message' => __( "Unsafe email config is used without sufficient protection.", 'contact-form-7' ),
)
);
} else {
$this->remove_error( $section, 'unsafe_email_without_protection' );
}
}
}
/**
* Runs error detection for the mail body section.
*/
public function validate_mail_body( $template, $content ) {
$section = sprintf( '%s.body', $template );
if ( $this->supports( 'maybe_empty' ) ) {
if ( $this->detect_maybe_empty( $section, $content ) ) {
$this->add_error( $section, 'maybe_empty',
array(
'message' => __( "There is a possible empty field.", 'contact-form-7' ),
)
);
} else {
$this->remove_error( $section, 'maybe_empty' );
}
}
}
/**
* Runs error detection for the mail attachments section.
*/
public function validate_mail_attachments( $template, $content ) {
$section = sprintf( '%s.attachments', $template );
$total_size = 0;
$files_not_found = array();
$files_out_of_content = array();
if ( '' !== $content ) {
$attachables = array();
$tags = $this->contact_form->scan_form_tags(
array( 'type' => array( 'file', 'file*' ) )
);
foreach ( $tags as $tag ) {
$name = $tag->name;
if ( ! str_contains( $content, "[{$name}]" ) ) {
continue;
}
$limit = (int) $tag->get_limit_option();
if ( empty( $attachables[$name] ) or $attachables[$name] < $limit ) {
$attachables[$name] = $limit;
}
}
$total_size = array_sum( $attachables );
foreach ( explode( "\n", $content ) as $line ) {
$line = trim( $line );
if ( '' === $line or str_starts_with( $line, '[' ) ) {
continue;
}
if ( $this->detect_file_not_found( $section, $line ) ) {
$files_not_found[] = $line;
} elseif ( $this->detect_file_not_in_content_dir( $section, $line ) ) {
$files_out_of_content[] = $line;
} else {
$total_size += (int) @filesize( $path );
}
}
}
if ( $this->supports( 'file_not_found' ) ) {
if ( ! empty( $files_not_found ) ) {
foreach ( $files_not_found as $line ) {
$this->add_error( $section, 'file_not_found',
array(
'message' => __( "Attachment file does not exist at %path%.", 'contact-form-7' ),
'params' => array( 'path' => $line ),
)
);
}
} else {
$this->remove_error( $section, 'file_not_found' );
}
}
if ( $this->supports( 'file_not_in_content_dir' ) ) {
if ( ! empty( $files_out_of_content ) ) {
$this->add_error( $section, 'file_not_in_content_dir',
array(
'message' => __( "It is not allowed to use files outside the wp-content directory.", 'contact-form-7' ),
)
);
} else {
$this->remove_error( $section, 'file_not_in_content_dir' );
}
}
if ( $this->supports( 'attachments_overweight' ) ) {
$max = 25 * MB_IN_BYTES; // 25 MB
if ( $max < $total_size ) {
$this->add_error( $section, 'attachments_overweight',
array(
'message' => __( "The total size of attachment files is too large.", 'contact-form-7' ),
)
);
} else {
$this->remove_error( $section, 'attachments_overweight' );
}
}
}
/**
* Detects errors of invalid mailbox syntax.
*
* @link https://contactform7.com/configuration-errors/invalid-mailbox-syntax/
*/
public function detect_invalid_mailbox_syntax( $section, $content ) {
$content = $this->replace_mail_tags( $content );
$content = wpcf7_strip_newline( $content );
if ( ! wpcf7_is_mailbox_list( $content ) ) {
return true;
}
return false;
}
/**
* Detects errors of empty message fields.
*
* @link https://contactform7.com/configuration-errors/maybe-empty/
*/
public function detect_maybe_empty( $section, $content ) {
$content = $this->replace_mail_tags( $content );
$content = wpcf7_strip_newline( $content );
if ( '' === $content ) {
return true;
}
return false;
}
/**
* Detects errors of nonexistent attachment files.
*
* @link https://contactform7.com/configuration-errors/file-not-found/
*/
public function detect_file_not_found( $section, $content ) {
$path = path_join( WP_CONTENT_DIR, $content );
if ( ! is_readable( $path ) or ! is_file( $path ) ) {
return true;
}
return false;
}
/**
* Detects errors of attachment files out of the content directory.
*
* @link https://contactform7.com/configuration-errors/file-not-in-content-dir/
*/
public function detect_file_not_in_content_dir( $section, $content ) {
$path = path_join( WP_CONTENT_DIR, $content );
if ( ! wpcf7_is_file_path_in_content_dir( $path ) ) {
return true;
}
return false;
}
/**
* Detects errors of that unsafe email config is used without
* sufficient protection.
*
* @link https://contactform7.com/configuration-errors/unsafe-email-without-protection/
*/
public function detect_unsafe_email_without_protection( $section, $content ) {
static $is_recaptcha_active = null;
if ( null === $is_recaptcha_active ) {
$is_recaptcha_active = call_user_func( function () {
$service = WPCF7_RECAPTCHA::get_instance();
return $service->is_active();
} );
}
if ( $is_recaptcha_active ) {
return false;
}
$example_email = 'user-specified@example.com';
// Replace mail-tags connected to an email type form-tag first.
$content = $this->replace_mail_tags( $content, array(
'callback' => function ( $matches ) use ( $example_email ) {
// allow [[foo]] syntax for escaping a tag
if ( $matches[1] === '[' and $matches[4] === ']' ) {
return substr( $matches[0], 1, -1 );
}
$tag = $matches[0];
$tagname = $matches[2];
$values = $matches[3];
$mail_tag = new WPCF7_MailTag( $tag, $tagname, $values );
$field_name = $mail_tag->field_name();
$form_tags = $this->contact_form->scan_form_tags(
array( 'name' => $field_name )
);
if ( $form_tags ) {
$form_tag = new WPCF7_FormTag( $form_tags[0] );
if ( 'email' === $form_tag->basetype ) {
return $example_email;
}
}
return $tag;
},
) );
// Replace remaining mail-tags.
$content = $this->replace_mail_tags( $content );
$content = wpcf7_strip_newline( $content );
if ( str_contains( $content, $example_email ) ) {
return true;
}
return false;
}
}

View File

@@ -1,55 +0,0 @@
<?php
trait WPCF7_ConfigValidator_Messages {
/**
* Runs error detection for the messages section.
*/
public function validate_messages() {
$messages = (array) $this->contact_form->prop( 'messages' );
if ( ! $messages ) {
return;
}
if (
isset( $messages['captcha_not_match'] ) and
! wpcf7_use_really_simple_captcha()
) {
unset( $messages['captcha_not_match'] );
}
foreach ( $messages as $key => $message ) {
$section = sprintf( 'messages.%s', $key );
if ( $this->supports( 'html_in_message' ) ) {
if ( $this->detect_html_in_message( $section, $message ) ) {
$this->add_error( $section, 'html_in_message',
array(
'message' => __( "HTML tags are used in a message.", 'contact-form-7' ),
)
);
} else {
$this->remove_error( $section, 'html_in_message' );
}
}
}
}
/**
* Detects errors of HTML uses in a message.
*
* @link https://contactform7.com/configuration-errors/html-in-message/
*/
public function detect_html_in_message( $section, $content ) {
$stripped = wp_strip_all_tags( $content );
if ( $stripped !== $content ) {
return true;
}
return false;
}
}

View File

@@ -1,376 +0,0 @@
<?php
require_once path_join( __DIR__, 'form.php' );
require_once path_join( __DIR__, 'mail.php' );
require_once path_join( __DIR__, 'messages.php' );
require_once path_join( __DIR__, 'additional-settings.php' );
require_once path_join( __DIR__, 'actions.php' );
/**
* Configuration validator.
*
* @link https://contactform7.com/configuration-errors/
*/
class WPCF7_ConfigValidator {
/**
* The plugin version in which important updates happened last time.
*/
const last_important_update = '5.8.1';
const error_codes = array(
'maybe_empty',
'invalid_mailbox_syntax',
'email_not_in_site_domain',
'html_in_message',
'multiple_controls_in_label',
'file_not_found',
'unavailable_names',
'invalid_mail_header',
'deprecated_settings',
'file_not_in_content_dir',
'unavailable_html_elements',
'attachments_overweight',
'dots_in_names',
'colons_in_names',
'upload_filesize_overlimit',
'unsafe_email_without_protection',
);
use WPCF7_ConfigValidator_Form;
use WPCF7_ConfigValidator_Mail;
use WPCF7_ConfigValidator_Messages;
use WPCF7_ConfigValidator_AdditionalSettings;
private $contact_form;
private $errors = array();
private $include;
private $exclude;
/**
* Returns a URL linking to the documentation page for the error type.
*/
public static function get_doc_link( $child_page = '' ) {
$url = __( 'https://contactform7.com/configuration-errors/',
'contact-form-7'
);
if ( '' !== $child_page ) {
$child_page = strtr( $child_page, '_', '-' );
$url = sprintf( '%s/%s', untrailingslashit( $url ), $child_page );
}
return esc_url( $url );
}
/**
* Constructor.
*/
public function __construct( WPCF7_ContactForm $contact_form, $args = '' ) {
$args = wp_parse_args( $args, array(
'include' => null,
'exclude' => null,
) );
$this->contact_form = $contact_form;
if ( isset( $args['include'] ) ) {
$this->include = (array) $args['include'];
}
if ( isset( $args['exclude'] ) ) {
$this->exclude = (array) $args['exclude'];
}
}
/**
* Returns the contact form object that is tied to this validator.
*/
public function contact_form() {
return $this->contact_form;
}
/**
* Returns true if no error has been detected.
*/
public function is_valid() {
return ! $this->count_errors();
}
/**
* Returns true if the given error code is supported by this instance.
*/
public function supports( $error_code ) {
if ( isset( $this->include ) ) {
$supported_codes = array_intersect( self::error_codes, $this->include );
} else {
$supported_codes = self::error_codes;
}
if ( isset( $this->exclude ) ) {
$supported_codes = array_diff( $supported_codes, $this->exclude );
}
return in_array( $error_code, $supported_codes, true );
}
/**
* Counts detected errors.
*/
public function count_errors( $args = '' ) {
$args = wp_parse_args( $args, array(
'section' => '',
'code' => '',
) );
$count = 0;
foreach ( $this->errors as $key => $errors ) {
if ( preg_match( '/^mail_[0-9]+\.(.*)$/', $key, $matches ) ) {
$key = sprintf( 'mail.%s', $matches[1] );
}
if ( $args['section']
and $key !== $args['section']
and preg_replace( '/\..*$/', '', $key, 1 ) !== $args['section'] ) {
continue;
}
foreach ( $errors as $error ) {
if ( empty( $error ) ) {
continue;
}
if ( $args['code'] and $error['code'] !== $args['code'] ) {
continue;
}
$count += 1;
}
}
return $count;
}
/**
* Collects messages for detected errors.
*/
public function collect_error_messages() {
$error_messages = array();
foreach ( $this->errors as $section => $errors ) {
$error_messages[$section] = array();
foreach ( $errors as $error ) {
if ( empty( $error['args']['message'] ) ) {
$message = $this->get_default_message( $error['code'] );
} elseif ( empty( $error['args']['params'] ) ) {
$message = $error['args']['message'];
} else {
$message = $this->build_message(
$error['args']['message'],
$error['args']['params']
);
}
$link = '';
if ( ! empty( $error['args']['link'] ) ) {
$link = $error['args']['link'];
}
$error_messages[$section][] = array(
'message' => $message,
'link' => esc_url( $link ),
);
}
}
return $error_messages;
}
/**
* Builds an error message by replacing placeholders.
*/
public function build_message( $message, $params = '' ) {
$params = wp_parse_args( $params, array() );
foreach ( $params as $key => $val ) {
if ( ! preg_match( '/^[0-9A-Za-z_]+$/', $key ) ) { // invalid key
continue;
}
$placeholder = '%' . $key . '%';
if ( false !== stripos( $message, $placeholder ) ) {
$message = str_ireplace( $placeholder, $val, $message );
}
}
return $message;
}
/**
* Returns a default message that is used when the message for the error
* is not specified.
*/
public function get_default_message( $code = '' ) {
return __( "Configuration error is detected.", 'contact-form-7' );
}
/**
* Returns true if the specified section has the specified error.
*
* @param string $section The section where the error detected.
* @param string $code The unique code of the error.
*/
public function has_error( $section, $code ) {
if ( empty( $this->errors[$section] ) ) {
return false;
}
foreach ( (array) $this->errors[$section] as $error ) {
if ( isset( $error['code'] ) and $error['code'] === $code ) {
return true;
}
}
return false;
}
/**
* Adds a validation error.
*
* @param string $section The section where the error detected.
* @param string $code The unique code of the error.
* @param string|array $args Optional options for the error.
*/
public function add_error( $section, $code, $args = '' ) {
$args = wp_parse_args( $args, array(
'message' => '',
'params' => array(),
) );
$available_error_codes = (array) apply_filters(
'wpcf7_config_validator_available_error_codes',
self::error_codes,
$this->contact_form
);
if ( ! in_array( $code, $available_error_codes, true ) ) {
return false;
}
if ( ! isset( $args['link'] ) ) {
$args['link'] = self::get_doc_link( $code );
}
if ( ! isset( $this->errors[$section] ) ) {
$this->errors[$section] = array();
}
$this->errors[$section][] = array(
'code' => $code,
'args' => $args,
);
return true;
}
/**
* Removes an error.
*
* @param string $section The section where the error detected.
* @param string $code The unique code of the error.
*/
public function remove_error( $section, $code ) {
if ( empty( $this->errors[$section] ) ) {
return;
}
foreach ( (array) $this->errors[$section] as $key => $error ) {
if ( isset( $error['code'] ) and $error['code'] === $code ) {
unset( $this->errors[$section][$key] );
}
}
if ( empty( $this->errors[$section] ) ) {
unset( $this->errors[$section] );
}
}
/**
* The main validation runner.
*
* @return bool True if there is no error detected.
*/
public function validate() {
$this->validate_form();
$this->validate_mail( 'mail' );
$this->validate_mail( 'mail_2' );
$this->validate_messages();
$this->validate_additional_settings();
do_action( 'wpcf7_config_validator_validate', $this );
return $this->is_valid();
}
/**
* Saves detected errors as a post meta data.
*/
public function save() {
if ( $this->contact_form->initial() ) {
return;
}
delete_post_meta( $this->contact_form->id(), '_config_validation' );
if ( $this->errors ) {
update_post_meta(
$this->contact_form->id(), '_config_validation', $this->errors
);
}
}
/**
* Restore errors from the database.
*/
public function restore() {
$config_errors = get_post_meta(
$this->contact_form->id(), '_config_validation', true
);
foreach ( (array) $config_errors as $section => $errors ) {
if ( empty( $errors ) ) {
continue;
}
foreach ( (array) $errors as $error ) {
if ( ! empty( $error['code'] ) ) {
$code = $error['code'];
$args = isset( $error['args'] ) ? $error['args'] : '';
$this->add_error( $section, $code, $args );
}
}
}
}
}

View File

@@ -1,471 +0,0 @@
<?php
/**
* Contact form helper functions
*/
/**
* Wrapper function of WPCF7_ContactForm::get_instance().
*
* @param WPCF7_ContactForm|WP_Post|int $post Object or post ID.
* @return WPCF7_ContactForm|null Contact form object. Null if unset.
*/
function wpcf7_contact_form( $post ) {
return WPCF7_ContactForm::get_instance( $post );
}
/**
* Searches for a contact form by an old unit ID.
*
* @param int $old_id Old unit ID.
* @return WPCF7_ContactForm Contact form object.
*/
function wpcf7_get_contact_form_by_old_id( $old_id ) {
global $wpdb;
$q = "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_old_cf7_unit_id'"
. $wpdb->prepare( " AND meta_value = %d", $old_id );
if ( $new_id = $wpdb->get_var( $q ) ) {
return wpcf7_contact_form( $new_id );
}
}
/**
* Searches for a contact form by a hash string.
*
* @param string $hash Part of a hash string.
* @return WPCF7_ContactForm Contact form object.
*/
function wpcf7_get_contact_form_by_hash( $hash ) {
global $wpdb;
$hash = trim( $hash );
if ( strlen( $hash ) < 7 ) {
return null;
}
$like = $wpdb->esc_like( $hash ) . '%';
$q = "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_hash'"
. $wpdb->prepare( " AND meta_value LIKE %s", $like );
if ( $post_id = $wpdb->get_var( $q ) ) {
return wpcf7_contact_form( $post_id );
}
}
/**
* Searches for a contact form by title.
*
* @param string $title Title of contact form.
* @return WPCF7_ContactForm|null Contact form object if found, null otherwise.
*/
function wpcf7_get_contact_form_by_title( $title ) {
if ( ! is_string( $title ) or '' === $title ) {
return null;
}
$contact_forms = WPCF7_ContactForm::find( array(
'title' => $title,
'posts_per_page' => 1,
) );
if ( $contact_forms ) {
return wpcf7_contact_form( reset( $contact_forms ) );
}
}
/**
* Wrapper function of WPCF7_ContactForm::get_current().
*
* @return WPCF7_ContactForm Contact form object.
*/
function wpcf7_get_current_contact_form() {
if ( $current = WPCF7_ContactForm::get_current() ) {
return $current;
}
}
/**
* Returns true if it is in the state that a non-Ajax submission is accepted.
*/
function wpcf7_is_posted() {
if ( ! $contact_form = wpcf7_get_current_contact_form() ) {
return false;
}
return $contact_form->is_posted();
}
/**
* Retrieves the user input value through a non-Ajax submission.
*
* @param string $name Name of form control.
* @param string $default_value Optional default value.
* @return string The user input value through the form-control.
*/
function wpcf7_get_hangover( $name, $default_value = null ) {
if ( ! wpcf7_is_posted() ) {
return $default_value;
}
$submission = WPCF7_Submission::get_instance();
if ( ! $submission
or $submission->is( 'mail_sent' ) ) {
return $default_value;
}
return isset( $_POST[$name] ) ? wp_unslash( $_POST[$name] ) : $default_value;
}
/**
* Retrieves an HTML snippet of validation error on the given form control.
*
* @param string $name Name of form control.
* @return string Validation error message in a form of HTML snippet.
*/
function wpcf7_get_validation_error( $name ) {
if ( ! $contact_form = wpcf7_get_current_contact_form() ) {
return '';
}
return $contact_form->validation_error( $name );
}
/**
* Returns a reference key to a validation error message.
*
* @param string $name Name of form control.
* @param string $unit_tag Optional. Unit tag of the contact form.
* @return string Reference key code.
*/
function wpcf7_get_validation_error_reference( $name, $unit_tag = '' ) {
if ( '' === $unit_tag ) {
$contact_form = wpcf7_get_current_contact_form();
if ( $contact_form and $contact_form->validation_error( $name ) ) {
$unit_tag = $contact_form->unit_tag();
} else {
return null;
}
}
return preg_replace( '/[^0-9a-z_-]+/i', '',
sprintf(
'%1$s-ve-%2$s',
$unit_tag,
$name
)
);
}
/**
* Retrieves a message for the given status.
*/
function wpcf7_get_message( $status ) {
if ( ! $contact_form = wpcf7_get_current_contact_form() ) {
return '';
}
return $contact_form->message( $status );
}
/**
* Returns a class names list for a form-tag of the specified type.
*
* @param string $type Form-tag type.
* @param string $default_classes Optional default classes.
* @return string Whitespace-separated list of class names.
*/
function wpcf7_form_controls_class( $type, $default_classes = '' ) {
$type = trim( $type );
if ( is_string( $default_classes ) ) {
$default_classes = explode( ' ', $default_classes );
}
$classes = array(
'wpcf7-form-control',
sprintf( 'wpcf7-%s', rtrim( $type, '*' ) ),
);
if ( str_ends_with( $type, '*' ) ) {
$classes[] = 'wpcf7-validates-as-required';
}
$classes = array_merge( $classes, $default_classes );
$classes = array_filter( array_unique( $classes ) );
return implode( ' ', $classes );
}
/**
* Callback function for the contact-form-7 shortcode.
*/
function wpcf7_contact_form_tag_func( $atts, $content = null, $code = '' ) {
if ( is_feed() ) {
return '[contact-form-7]';
}
if ( 'contact-form-7' === $code ) {
$atts = shortcode_atts(
array(
'id' => '',
'title' => '',
'html_id' => '',
'html_name' => '',
'html_title' => '',
'html_class' => '',
'output' => 'form',
),
$atts, 'wpcf7'
);
$id = trim( $atts['id'] );
$title = trim( $atts['title'] );
$contact_form = wpcf7_get_contact_form_by_hash( $id );
if ( ! $contact_form ) {
$contact_form = wpcf7_contact_form( $id );
}
if ( ! $contact_form ) {
$contact_form = wpcf7_get_contact_form_by_title( $title );
}
} else {
if ( is_string( $atts ) ) {
$atts = explode( ' ', $atts, 2 );
}
$id = (int) array_shift( $atts );
$contact_form = wpcf7_get_contact_form_by_old_id( $id );
}
if ( ! $contact_form ) {
return sprintf(
'<p class="wpcf7-contact-form-not-found"><strong>%1$s</strong> %2$s</p>',
esc_html( __( 'Error:', 'contact-form-7' ) ),
esc_html( __( "Contact form not found.", 'contact-form-7' ) )
);
}
$callback = static function ( $contact_form, $atts ) {
return $contact_form->form_html( $atts );
};
$output = wpcf7_switch_locale(
$contact_form->locale(),
$callback,
$contact_form, $atts
);
do_action( 'wpcf7_shortcode_callback', $contact_form, $atts );
return $output;
}
/**
* Saves the contact form data.
*/
function wpcf7_save_contact_form( $args = '', $context = 'save' ) {
$args = wp_parse_args( $args, array(
'id' => -1,
'title' => null,
'locale' => null,
'form' => null,
'mail' => null,
'mail_2' => null,
'messages' => null,
'additional_settings' => null,
) );
$args = wp_unslash( $args );
$args['id'] = (int) $args['id'];
if ( -1 == $args['id'] ) {
$contact_form = WPCF7_ContactForm::get_template();
} else {
$contact_form = wpcf7_contact_form( $args['id'] );
}
if ( empty( $contact_form ) ) {
return false;
}
if ( null !== $args['title'] ) {
$contact_form->set_title( $args['title'] );
}
if ( null !== $args['locale'] ) {
$contact_form->set_locale( $args['locale'] );
}
$properties = array();
if ( null !== $args['form'] ) {
$properties['form'] = wpcf7_sanitize_form( $args['form'] );
}
if ( null !== $args['mail'] ) {
$properties['mail'] = wpcf7_sanitize_mail( $args['mail'] );
$properties['mail']['active'] = true;
}
if ( null !== $args['mail_2'] ) {
$properties['mail_2'] = wpcf7_sanitize_mail( $args['mail_2'] );
}
if ( null !== $args['messages'] ) {
$properties['messages'] = wpcf7_sanitize_messages( $args['messages'] );
}
if ( null !== $args['additional_settings'] ) {
$properties['additional_settings'] = wpcf7_sanitize_additional_settings(
$args['additional_settings']
);
}
$contact_form->set_properties( $properties );
do_action( 'wpcf7_save_contact_form', $contact_form, $args, $context );
if ( 'save' == $context ) {
$contact_form->save();
}
return $contact_form;
}
/**
* Sanitizes the form property data.
*/
function wpcf7_sanitize_form( $input, $default_template = '' ) {
if ( null === $input ) {
return $default_template;
}
$output = trim( $input );
if ( ! current_user_can( 'unfiltered_html' ) ) {
$output = wpcf7_kses( $output, 'form' );
}
return $output;
}
/**
* Sanitizes the mail property data.
*/
function wpcf7_sanitize_mail( $input, $defaults = array() ) {
$input = wp_parse_args( $input, array(
'active' => false,
'subject' => '',
'sender' => '',
'recipient' => '',
'body' => '',
'additional_headers' => '',
'attachments' => '',
'use_html' => false,
'exclude_blank' => false,
) );
$input = wp_parse_args( $input, $defaults );
$output = array();
$output['active'] = (bool) $input['active'];
$output['subject'] = trim( $input['subject'] );
$output['sender'] = trim( $input['sender'] );
$output['recipient'] = trim( $input['recipient'] );
$output['body'] = trim( $input['body'] );
if ( ! current_user_can( 'unfiltered_html' ) ) {
$output['body'] = wpcf7_kses( $output['body'], 'mail' );
}
$output['additional_headers'] = '';
$headers = str_replace( "\r\n", "\n", $input['additional_headers'] );
$headers = explode( "\n", $headers );
foreach ( $headers as $header ) {
$header = trim( $header );
if ( '' !== $header ) {
$output['additional_headers'] .= $header . "\n";
}
}
$output['additional_headers'] = trim( $output['additional_headers'] );
$output['attachments'] = trim( $input['attachments'] );
$output['use_html'] = (bool) $input['use_html'];
$output['exclude_blank'] = (bool) $input['exclude_blank'];
return $output;
}
/**
* Sanitizes the messages property data.
*/
function wpcf7_sanitize_messages( $input, $defaults = array() ) {
$output = array();
foreach ( wpcf7_messages() as $key => $val ) {
if ( isset( $input[$key] ) ) {
$output[$key] = trim( $input[$key] );
} elseif ( isset( $defaults[$key] ) ) {
$output[$key] = $defaults[$key];
}
}
return $output;
}
/**
* Sanitizes the additional settings property data.
*/
function wpcf7_sanitize_additional_settings( $input, $default_template = '' ) {
if ( null === $input ) {
return $default_template;
}
$output = trim( $input );
return $output;
}
/**
* Generates a random hash string for a contact form.
*
* @param int $post_id Post ID.
* @return string SHA-1 hash.
*/
function wpcf7_generate_contact_form_hash( $post_id ) {
return sha1( implode( '|', array(
get_current_user_id(),
$post_id,
time(),
home_url(),
) ) );
}

View File

@@ -1,220 +0,0 @@
<?php
class WPCF7_ContactFormTemplate {
public static function get_default( $prop = 'form' ) {
if ( 'form' == $prop ) {
$template = self::form();
} elseif ( 'mail' == $prop ) {
$template = self::mail();
} elseif ( 'mail_2' == $prop ) {
$template = self::mail_2();
} elseif ( 'messages' == $prop ) {
$template = self::messages();
} else {
$template = null;
}
return apply_filters( 'wpcf7_default_template', $template, $prop );
}
public static function form() {
$template = sprintf(
'
<label> %2$s
[text* your-name autocomplete:name] </label>
<label> %3$s
[email* your-email autocomplete:email] </label>
<label> %4$s
[text* your-subject] </label>
<label> %5$s %1$s
[textarea your-message] </label>
[submit "%6$s"]',
__( '(optional)', 'contact-form-7' ),
__( 'Your name', 'contact-form-7' ),
__( 'Your email', 'contact-form-7' ),
__( 'Subject', 'contact-form-7' ),
__( 'Your message', 'contact-form-7' ),
__( 'Submit', 'contact-form-7' )
);
return trim( $template );
}
public static function mail() {
$template = array(
'subject' => sprintf(
/* translators: 1: blog name, 2: [your-subject] */
_x( '%1$s "%2$s"', 'mail subject', 'contact-form-7' ),
'[_site_title]',
'[your-subject]'
),
'sender' => sprintf(
'%s <%s>',
'[_site_title]',
self::from_email()
),
'body' =>
sprintf(
/* translators: %s: [your-name] [your-email] */
__( 'From: %s', 'contact-form-7' ),
'[your-name] [your-email]'
) . "\n"
. sprintf(
/* translators: %s: [your-subject] */
__( 'Subject: %s', 'contact-form-7' ),
'[your-subject]'
) . "\n\n"
. __( 'Message Body:', 'contact-form-7' )
. "\n" . '[your-message]' . "\n\n"
. '-- ' . "\n"
. sprintf(
/* translators: 1: blog name, 2: blog URL */
__( 'This is a notification that a contact form was submitted on your website (%1$s %2$s).', 'contact-form-7' ),
'[_site_title]',
'[_site_url]'
),
'recipient' => '[_site_admin_email]',
'additional_headers' => 'Reply-To: [your-email]',
'attachments' => '',
'use_html' => 0,
'exclude_blank' => 0,
);
return $template;
}
public static function mail_2() {
$template = array(
'active' => false,
'subject' => sprintf(
/* translators: 1: blog name, 2: [your-subject] */
_x( '%1$s "%2$s"', 'mail subject', 'contact-form-7' ),
'[_site_title]',
'[your-subject]'
),
'sender' => sprintf(
'%s <%s>',
'[_site_title]',
self::from_email()
),
'body' =>
__( 'Message Body:', 'contact-form-7' )
. "\n" . '[your-message]' . "\n\n"
. '-- ' . "\n"
. sprintf(
/* translators: 1: blog name, 2: blog URL */
__( 'This email is a receipt for your contact form submission on our website (%1$s %2$s) in which your email address was used. If that was not you, please ignore this message.', 'contact-form-7' ),
'[_site_title]',
'[_site_url]'
),
'recipient' => '[your-email]',
'additional_headers' => sprintf(
'Reply-To: %s',
'[_site_admin_email]'
),
'attachments' => '',
'use_html' => 0,
'exclude_blank' => 0,
);
return $template;
}
public static function from_email() {
$admin_email = get_option( 'admin_email' );
if ( wpcf7_is_localhost() ) {
return $admin_email;
}
$sitename = wp_parse_url( network_home_url(), PHP_URL_HOST );
$sitename = strtolower( $sitename );
if ( 'www.' === substr( $sitename, 0, 4 ) ) {
$sitename = substr( $sitename, 4 );
}
if ( strpbrk( $admin_email, '@' ) === '@' . $sitename ) {
return $admin_email;
}
return 'wordpress@' . $sitename;
}
public static function messages() {
$messages = array();
foreach ( wpcf7_messages() as $key => $arr ) {
$messages[$key] = $arr['default'];
}
return $messages;
}
}
function wpcf7_messages() {
$messages = array(
'mail_sent_ok' => array(
'description'
=> __( "Sender's message was sent successfully", 'contact-form-7' ),
'default'
=> __( "Thank you for your message. It has been sent.", 'contact-form-7' ),
),
'mail_sent_ng' => array(
'description'
=> __( "Sender's message failed to send", 'contact-form-7' ),
'default'
=> __( "There was an error trying to send your message. Please try again later.", 'contact-form-7' ),
),
'validation_error' => array(
'description'
=> __( "Validation errors occurred", 'contact-form-7' ),
'default'
=> __( "One or more fields have an error. Please check and try again.", 'contact-form-7' ),
),
'spam' => array(
'description'
=> __( "Submission was referred to as spam", 'contact-form-7' ),
'default'
=> __( "There was an error trying to send your message. Please try again later.", 'contact-form-7' ),
),
'accept_terms' => array(
'description'
=> __( "There are terms that the sender must accept", 'contact-form-7' ),
'default'
=> __( "You must accept the terms and conditions before sending your message.", 'contact-form-7' ),
),
'invalid_required' => array(
'description'
=> __( "There is a field that the sender must fill in", 'contact-form-7' ),
'default'
=> __( "Please fill out this field.", 'contact-form-7' ),
),
'invalid_too_long' => array(
'description'
=> __( "There is a field with input that is longer than the maximum allowed length", 'contact-form-7' ),
'default'
=> __( "This field has a too long input.", 'contact-form-7' ),
),
'invalid_too_short' => array(
'description'
=> __( "There is a field with input that is shorter than the minimum allowed length", 'contact-form-7' ),
'default'
=> __( "This field has a too short input.", 'contact-form-7' ),
),
);
return apply_filters( 'wpcf7_messages', $messages );
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,180 +0,0 @@
<?php
/**
* Controller for front-end requests, scripts, and styles
*/
add_action(
'parse_request',
'wpcf7_control_init',
20, 0
);
/**
* Handles a submission in non-Ajax mode.
*/
function wpcf7_control_init() {
if ( WPCF7_Submission::is_restful() ) {
return;
}
if ( isset( $_POST['_wpcf7'] ) ) {
$contact_form = wpcf7_contact_form( (int) $_POST['_wpcf7'] );
if ( $contact_form ) {
$contact_form->submit();
}
}
}
/**
* Registers main scripts and styles.
*/
add_action(
'wp_enqueue_scripts',
static function () {
$assets = array();
$asset_file = wpcf7_plugin_path( 'includes/js/index.asset.php' );
if ( file_exists( $asset_file ) ) {
$assets = include( $asset_file );
}
$assets = wp_parse_args( $assets, array(
'dependencies' => array(),
'version' => WPCF7_VERSION,
) );
wp_register_script(
'contact-form-7',
wpcf7_plugin_url( 'includes/js/index.js' ),
array_merge(
$assets['dependencies'],
array( 'swv' )
),
$assets['version'],
true
);
wp_register_script(
'contact-form-7-html5-fallback',
wpcf7_plugin_url( 'includes/js/html5-fallback.js' ),
array( 'jquery-ui-datepicker' ),
WPCF7_VERSION,
true
);
if ( wpcf7_load_js() ) {
wpcf7_enqueue_scripts();
}
wp_register_style(
'contact-form-7',
wpcf7_plugin_url( 'includes/css/styles.css' ),
array(),
WPCF7_VERSION,
'all'
);
wp_register_style(
'contact-form-7-rtl',
wpcf7_plugin_url( 'includes/css/styles-rtl.css' ),
array( 'contact-form-7' ),
WPCF7_VERSION,
'all'
);
wp_register_style(
'jquery-ui-smoothness',
wpcf7_plugin_url(
'includes/js/jquery-ui/themes/smoothness/jquery-ui.min.css'
),
array(),
'1.12.1',
'screen'
);
if ( wpcf7_load_css() ) {
wpcf7_enqueue_styles();
}
},
10, 0
);
/**
* Enqueues scripts.
*/
function wpcf7_enqueue_scripts() {
wp_enqueue_script( 'contact-form-7' );
$wpcf7 = array(
'api' => array(
'root' => sanitize_url( get_rest_url() ),
'namespace' => 'contact-form-7/v1',
),
);
if ( defined( 'WP_CACHE' ) and WP_CACHE ) {
$wpcf7['cached'] = 1;
}
wp_localize_script( 'contact-form-7', 'wpcf7', $wpcf7 );
do_action( 'wpcf7_enqueue_scripts' );
}
/**
* Returns true if the main script is enqueued.
*/
function wpcf7_script_is() {
return wp_script_is( 'contact-form-7' );
}
/**
* Enqueues styles.
*/
function wpcf7_enqueue_styles() {
wp_enqueue_style( 'contact-form-7' );
if ( wpcf7_is_rtl() ) {
wp_enqueue_style( 'contact-form-7-rtl' );
}
do_action( 'wpcf7_enqueue_styles' );
}
/**
* Returns true if the main stylesheet is enqueued.
*/
function wpcf7_style_is() {
return wp_style_is( 'contact-form-7' );
}
add_action(
'wp_enqueue_scripts',
'wpcf7_html5_fallback',
20, 0
);
/**
* Enqueues scripts and styles for the HTML5 fallback.
*/
function wpcf7_html5_fallback() {
if ( ! wpcf7_support_html5_fallback() ) {
return;
}
if ( wpcf7_script_is() ) {
wp_enqueue_script( 'contact-form-7-html5-fallback' );
}
if ( wpcf7_style_is() ) {
wp_enqueue_style( 'jquery-ui-smoothness' );
}
}

View File

@@ -1,11 +0,0 @@
.wpcf7-not-valid-tip {
direction: rtl;
}
.use-floating-validation-tip .wpcf7-not-valid-tip {
right: 1em;
}
.wpcf7-list-item {
margin: 0 1em 0 0;
}

View File

@@ -1,172 +0,0 @@
.wpcf7 .screen-reader-response {
position: absolute;
overflow: hidden;
clip: rect(1px, 1px, 1px, 1px);
clip-path: inset(50%);
height: 1px;
width: 1px;
margin: -1px;
padding: 0;
border: 0;
word-wrap: normal !important;
}
.wpcf7 form .wpcf7-response-output {
margin: 2em 0.5em 1em;
padding: 0.2em 1em;
border: 2px solid #00a0d2; /* Blue */
}
.wpcf7 form.init .wpcf7-response-output,
.wpcf7 form.resetting .wpcf7-response-output,
.wpcf7 form.submitting .wpcf7-response-output {
display: none;
}
.wpcf7 form.sent .wpcf7-response-output {
border-color: #46b450; /* Green */
}
.wpcf7 form.failed .wpcf7-response-output,
.wpcf7 form.aborted .wpcf7-response-output {
border-color: #dc3232; /* Red */
}
.wpcf7 form.spam .wpcf7-response-output {
border-color: #f56e28; /* Orange */
}
.wpcf7 form.invalid .wpcf7-response-output,
.wpcf7 form.unaccepted .wpcf7-response-output,
.wpcf7 form.payment-required .wpcf7-response-output {
border-color: #ffb900; /* Yellow */
}
.wpcf7-form-control-wrap {
position: relative;
}
.wpcf7-not-valid-tip {
color: #dc3232; /* Red */
font-size: 1em;
font-weight: normal;
display: block;
}
.use-floating-validation-tip .wpcf7-not-valid-tip {
position: relative;
top: -2ex;
left: 1em;
z-index: 100;
border: 1px solid #dc3232;
background: #fff;
padding: .2em .8em;
width: 24em;
}
.wpcf7-list-item {
display: inline-block;
margin: 0 0 0 1em;
}
.wpcf7-list-item-label::before,
.wpcf7-list-item-label::after {
content: " ";
}
.wpcf7-spinner {
visibility: hidden;
display: inline-block;
background-color: #23282d; /* Dark Gray 800 */
opacity: 0.75;
width: 24px;
height: 24px;
border: none;
border-radius: 100%;
padding: 0;
margin: 0 24px;
position: relative;
}
form.submitting .wpcf7-spinner {
visibility: visible;
}
.wpcf7-spinner::before {
content: '';
position: absolute;
background-color: #fbfbfc; /* Light Gray 100 */
top: 4px;
left: 4px;
width: 6px;
height: 6px;
border: none;
border-radius: 100%;
transform-origin: 8px 8px;
animation-name: spin;
animation-duration: 1000ms;
animation-timing-function: linear;
animation-iteration-count: infinite;
}
@media (prefers-reduced-motion: reduce) {
.wpcf7-spinner::before {
animation-name: blink;
animation-duration: 2000ms;
}
}
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
@keyframes blink {
from {
opacity: 0;
}
50% {
opacity: 1;
}
to {
opacity: 0;
}
}
.wpcf7 [inert] {
opacity: 0.5;
}
.wpcf7 input[type="file"] {
cursor: pointer;
}
.wpcf7 input[type="file"]:disabled {
cursor: default;
}
.wpcf7 .wpcf7-submit:disabled {
cursor: not-allowed;
}
.wpcf7 input[type="url"],
.wpcf7 input[type="email"],
.wpcf7 input[type="tel"] {
direction: ltr;
}
.wpcf7-reflection > output {
display: list-item;
list-style: none;
}
.wpcf7-reflection > output[hidden] {
display: none;
}

View File

@@ -1,424 +0,0 @@
<?php
/**
* Validates uploaded files and moves them to the temporary directory.
*
* @param array $file An item of `$_FILES`.
* @param string|array $args Optional. Arguments to control behavior.
* @return array|WP_Error Array of file paths, or WP_Error if validation fails.
*/
function wpcf7_unship_uploaded_file( $file, $args = '' ) {
$args = wp_parse_args( $args, array(
'required' => false,
'filetypes' => '',
'limit' => MB_IN_BYTES,
) );
foreach ( array( 'name', 'size', 'tmp_name', 'error' ) as $key ) {
if ( ! isset( $file[$key] ) ) {
$file[$key] = array();
}
}
$names = wpcf7_array_flatten( $file['name'] );
$sizes = wpcf7_array_flatten( $file['size'] );
$tmp_names = wpcf7_array_flatten( $file['tmp_name'] );
$errors = wpcf7_array_flatten( $file['error'] );
foreach ( $errors as $error ) {
if ( ! empty( $error ) and UPLOAD_ERR_NO_FILE !== $error ) {
return new WP_Error( 'wpcf7_upload_failed_php_error',
wpcf7_get_message( 'upload_failed_php_error' )
);
}
}
if ( isset( $args['schema'] ) and isset( $args['name'] ) ) {
$result = $args['schema']->validate( array(
'file' => true,
'field' => $args['name'],
) );
if ( is_wp_error( $result ) ) {
return $result;
}
}
// Move uploaded file to tmp dir
$uploads_dir = wpcf7_upload_tmp_dir();
$uploads_dir = wpcf7_maybe_add_random_dir( $uploads_dir );
$uploaded_files = array();
foreach ( $names as $key => $name ) {
$tmp_name = $tmp_names[$key];
if ( empty( $tmp_name ) or ! is_uploaded_file( $tmp_name ) ) {
continue;
}
$filename = $name;
$filename = wpcf7_canonicalize( $filename, array( 'strto' => 'as-is' ) );
$filename = wpcf7_antiscript_file_name( $filename );
$filename = apply_filters( 'wpcf7_upload_file_name',
$filename, $name, $args
);
$filename = wp_unique_filename( $uploads_dir, $filename );
$new_file = path_join( $uploads_dir, $filename );
if ( false === @move_uploaded_file( $tmp_name, $new_file ) ) {
return new WP_Error( 'wpcf7_upload_failed',
wpcf7_get_message( 'upload_failed' )
);
}
// Make sure the uploaded file is only readable for the owner process
chmod( $new_file, 0400 );
$uploaded_files[] = $new_file;
}
return $uploaded_files;
}
add_filter(
'wpcf7_messages',
'wpcf7_file_messages',
10, 1
);
/**
* A wpcf7_messages filter callback that adds messages for
* file-uploading fields.
*/
function wpcf7_file_messages( $messages ) {
return array_merge( $messages, array(
'upload_failed' => array(
'description' => __( "Uploading a file fails for any reason", 'contact-form-7' ),
'default' => __( "There was an unknown error uploading the file.", 'contact-form-7' ),
),
'upload_file_type_invalid' => array(
'description' => __( "Uploaded file is not allowed for file type", 'contact-form-7' ),
'default' => __( "You are not allowed to upload files of this type.", 'contact-form-7' ),
),
'upload_file_too_large' => array(
'description' => __( "Uploaded file is too large", 'contact-form-7' ),
'default' => __( "The uploaded file is too large.", 'contact-form-7' ),
),
'upload_failed_php_error' => array(
'description' => __( "Uploading a file fails for PHP error", 'contact-form-7' ),
'default' => __( "There was an error uploading the file.", 'contact-form-7' ),
),
) );
}
add_filter(
'wpcf7_form_enctype',
'wpcf7_file_form_enctype_filter',
10, 1
);
/**
* A wpcf7_form_enctype filter callback that sets the enctype attribute
* to multipart/form-data if the form has file-uploading fields.
*/
function wpcf7_file_form_enctype_filter( $enctype ) {
$multipart = (bool) wpcf7_scan_form_tags( array(
'feature' => 'file-uploading',
) );
if ( $multipart ) {
$enctype = 'multipart/form-data';
}
return $enctype;
}
/**
* Converts a MIME type string to an array of corresponding file extensions.
*
* @param string $mime MIME type.
* Wildcard (*) is available for the subtype part.
* @return array Corresponding file extensions.
*/
function wpcf7_convert_mime_to_ext( $mime ) {
static $mime_types = array();
$mime_types = wp_get_mime_types();
$results = array();
if ( preg_match( '%^([a-z]+)/([*]|[a-z0-9.+-]+)$%i', $mime, $matches ) ) {
foreach ( $mime_types as $key => $val ) {
if ( '*' === $matches[2] and str_starts_with( $val, $matches[1] . '/' )
or $val === $matches[0] ) {
$results = array_merge( $results, explode( '|', $key ) );
}
}
}
$results = array_unique( $results );
$results = array_filter( $results );
$results = array_values( $results );
return $results;
}
/**
* Returns a formatted list of acceptable filetypes.
*
* @param string|array $types Optional. Array of filetypes.
* @param string $format Optional. Pre-defined format designator.
* @return string Formatted list of acceptable filetypes.
*/
function wpcf7_acceptable_filetypes( $types = 'default', $format = 'regex' ) {
if ( 'default' === $types or empty( $types ) ) {
$types = array(
'audio/*',
'video/*',
'image/*',
);
} else {
$types = array_map(
static function ( $type ) {
if ( is_string( $type ) ) {
return preg_split( '/[\s|,]+/', strtolower( $type ) );
}
},
(array) $types
);
$types = wpcf7_array_flatten( $types );
$types = array_filter( array_unique( $types ) );
}
if ( 'attr' === $format or 'attribute' === $format ) {
$types = array_map(
static function ( $type ) {
if ( false === strpos( $type, '/' ) ) {
return sprintf( '.%s', trim( $type, '.' ) );
} elseif ( preg_match( '%^([a-z]+)/[*]$%i', $type, $matches ) ) {
if ( in_array( $matches[1], array( 'audio', 'video', 'image' ) ) ) {
return $type;
} else {
return '';
}
} elseif ( wpcf7_convert_mime_to_ext( $type ) ) {
return $type;
}
},
$types
);
$types = array_filter( $types );
return implode( ',', $types );
} elseif ( 'regex' === $format ) {
$types = array_map(
static function ( $type ) {
if ( false === strpos( $type, '/' ) ) {
return preg_quote( trim( $type, '.' ) );
} elseif ( $type = wpcf7_convert_mime_to_ext( $type ) ) {
return $type;
}
},
$types
);
$types = wpcf7_array_flatten( $types );
$types = array_filter( array_unique( $types ) );
return implode( '|', $types );
}
return '';
}
add_action(
'wpcf7_init',
'wpcf7_init_uploads',
10, 0
);
/**
* Initializes the temporary directory for uploaded files.
*/
function wpcf7_init_uploads() {
$dir = wpcf7_upload_tmp_dir();
if ( is_dir( $dir ) and is_writable( $dir ) ) {
$htaccess_file = path_join( $dir, '.htaccess' );
if ( file_exists( $htaccess_file ) ) {
list( $first_line_comment ) = (array) file(
$htaccess_file,
FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES
);
if ( '# Apache 2.4+' === $first_line_comment ) {
return;
}
}
if ( $handle = @fopen( $htaccess_file, 'w' ) ) {
fwrite( $handle, "# Apache 2.4+\n" );
fwrite( $handle, "<IfModule authz_core_module>\n" );
fwrite( $handle, " Require all denied\n" );
fwrite( $handle, "</IfModule>\n" );
fwrite( $handle, "\n" );
fwrite( $handle, "# Apache 2.2\n" );
fwrite( $handle, "<IfModule !authz_core_module>\n" );
fwrite( $handle, " Deny from all\n" );
fwrite( $handle, "</IfModule>\n" );
fclose( $handle );
}
}
}
/**
* Creates a child directory with a randomly generated name.
*
* @param string $dir The parent directory path.
* @return string The child directory path if created, otherwise the parent.
*/
function wpcf7_maybe_add_random_dir( $dir ) {
do {
$rand_max = mt_getrandmax();
$rand = zeroise( mt_rand( 0, $rand_max ), strlen( $rand_max ) );
$dir_new = path_join( $dir, $rand );
} while ( file_exists( $dir_new ) );
if ( wp_mkdir_p( $dir_new ) ) {
return $dir_new;
}
return $dir;
}
/**
* Returns the directory path for uploaded files.
*
* @return string Directory path.
*/
function wpcf7_upload_tmp_dir() {
if ( defined( 'WPCF7_UPLOADS_TMP_DIR' ) ) {
$dir = path_join( WP_CONTENT_DIR, WPCF7_UPLOADS_TMP_DIR );
wp_mkdir_p( $dir );
if ( wpcf7_is_file_path_in_content_dir( $dir ) ) {
return $dir;
}
}
$dir = path_join( wpcf7_upload_dir( 'dir' ), 'wpcf7_uploads' );
wp_mkdir_p( $dir );
return $dir;
}
add_action(
'shutdown',
'wpcf7_cleanup_upload_files',
20, 0
);
/**
* Cleans up files in the temporary directory for uploaded files.
*
* @param int $seconds Files older than this are removed. Default 60.
* @param int $max Maximum number of files to be removed in a function call.
* Default 100.
*/
function wpcf7_cleanup_upload_files( $seconds = 60, $max = 100 ) {
$dir = trailingslashit( wpcf7_upload_tmp_dir() );
if ( ! is_dir( $dir )
or ! is_readable( $dir )
or ! wp_is_writable( $dir ) ) {
return;
}
$seconds = absint( $seconds );
$max = absint( $max );
$count = 0;
if ( $handle = opendir( $dir ) ) {
while ( false !== ( $file = readdir( $handle ) ) ) {
if ( '.' == $file
or '..' == $file
or '.htaccess' == $file ) {
continue;
}
$mtime = @filemtime( path_join( $dir, $file ) );
if ( $mtime and time() < $mtime + $seconds ) { // less than $seconds old
continue;
}
wpcf7_rmdir_p( path_join( $dir, $file ) );
$count += 1;
if ( $max <= $count ) {
break;
}
}
closedir( $handle );
}
}
add_action(
'wpcf7_admin_warnings',
'wpcf7_file_display_warning_message',
10, 3
);
/**
* Displays warning messages about file-uploading fields.
*/
function wpcf7_file_display_warning_message( $page, $action, $object ) {
if ( $object instanceof WPCF7_ContactForm ) {
$contact_form = $object;
} else {
return;
}
$has_tags = (bool) $contact_form->scan_form_tags( array(
'feature' => 'file-uploading',
) );
if ( ! $has_tags ) {
return;
}
$uploads_dir = wpcf7_upload_tmp_dir();
if ( ! is_dir( $uploads_dir ) or ! wp_is_writable( $uploads_dir ) ) {
$message = sprintf(
/* translators: %s: the path of the temporary folder */
__( 'This contact form has file uploading fields, but the temporary folder for the files (%s) does not exist or is not writable. You can create the folder or change its permission manually.', 'contact-form-7' ),
$uploads_dir
);
echo sprintf(
'<div class="notice notice-warning"><p>%s</p></div>',
esc_html( $message )
);
}
}

View File

@@ -1,580 +0,0 @@
<?php
/**
* A form-tag.
*
* @link https://contactform7.com/tag-syntax/#form_tag
*/
class WPCF7_FormTag implements ArrayAccess {
public $type;
public $basetype;
public $raw_name = '';
public $name = '';
public $options = array();
public $raw_values = array();
public $values = array();
public $pipes;
public $labels = array();
public $attr = '';
public $content = '';
public function __construct( $tag = array() ) {
if ( is_array( $tag )
or $tag instanceof self ) {
foreach ( $tag as $key => $value ) {
if ( property_exists( __CLASS__, $key ) ) {
$this->{$key} = $value;
}
}
}
}
/**
* Returns true if the type has a trailing asterisk.
*/
public function is_required() {
return str_ends_with( $this->type, '*' );
}
/**
* Returns true if the form-tag has a specified option.
*/
public function has_option( $option_name ) {
$pattern = sprintf( '/^%s(:.+)?$/i', preg_quote( $option_name, '/' ) );
return (bool) preg_grep( $pattern, $this->options );
}
/**
* Retrieves option values with the specified option name.
*
* @param string $option_name Option name.
* @param string $pattern Optional. A regular expression pattern or one of
* the keys of preset patterns. If specified, only options
* whose value part matches this pattern will be returned.
* @param bool $single Optional. If true, only the first matching option
* will be returned. Default false.
* @return string|array|bool The option value or an array of option values.
* False if there is no option matches the pattern.
*/
public function get_option( $option_name, $pattern = '', $single = false ) {
$preset_patterns = array(
'date' => '[0-9]{4}-[0-9]{2}-[0-9]{2}',
'int' => '[0-9]+',
'signed_int' => '[-]?[0-9]+',
'num' => '(?:[0-9]+|(?:[0-9]+)?[.][0-9]+)',
'signed_num' => '[-]?(?:[0-9]+|(?:[0-9]+)?[.][0-9]+)',
'class' => '[-0-9a-zA-Z_]+',
'id' => '[-0-9a-zA-Z_]+',
);
if ( isset( $preset_patterns[$pattern] ) ) {
$pattern = $preset_patterns[$pattern];
}
if ( '' == $pattern ) {
$pattern = '.+';
}
$pattern = sprintf(
'/^%s:%s$/i',
preg_quote( $option_name, '/' ),
$pattern
);
if ( $single ) {
$matches = $this->get_first_match_option( $pattern );
if ( ! $matches ) {
return false;
}
return substr( $matches[0], strlen( $option_name ) + 1 );
} else {
$matches_a = $this->get_all_match_options( $pattern );
if ( ! $matches_a ) {
return false;
}
$results = array();
foreach ( $matches_a as $matches ) {
$results[] = substr( $matches[0], strlen( $option_name ) + 1 );
}
return $results;
}
}
/**
* Retrieves the id option value from the form-tag.
*/
public function get_id_option() {
static $used = array();
$option = $this->get_option( 'id', 'id', true );
if (
! $option or
str_starts_with( $option, 'wpcf7' ) or
in_array( $option, $used, true )
) {
return false;
}
$used[] = $option;
return $option;
}
/**
* Retrieves the class option value from the form-tag.
*
* @param string|array $default_classes Optional. Preset classes as an array
* or a whitespace-separated list. Default empty string.
* @return string|bool A whitespace-separated list of classes.
* False if there is no class to return.
*/
public function get_class_option( $default_classes = '' ) {
if ( is_string( $default_classes ) ) {
$default_classes = explode( ' ', $default_classes );
}
$options = array_merge(
(array) $default_classes,
(array) $this->get_option( 'class' )
);
$options = array_map( 'sanitize_html_class', $options );
$options = array_filter( array_unique( $options ) );
if ( empty( $options ) ) {
return false;
}
return implode( ' ', $options );
}
/**
* Retrieves the size option value from the form-tag.
*
* @param string $default_value Optional default value.
* @return string The option value.
*/
public function get_size_option( $default_value = false ) {
$option = $this->get_option( 'size', 'int', true );
if ( $option ) {
return $option;
}
$matches_a = $this->get_all_match_options( '%^([0-9]*)/[0-9]*$%' );
foreach ( (array) $matches_a as $matches ) {
if ( isset( $matches[1] ) and '' !== $matches[1] ) {
return $matches[1];
}
}
return $default_value;
}
/**
* Retrieves the maxlength option value from the form-tag.
*
* @param string $default_value Optional default value.
* @return string The option value.
*/
public function get_maxlength_option( $default_value = false ) {
$option = $this->get_option( 'maxlength', 'int', true );
if ( $option ) {
return $option;
}
$matches_a = $this->get_all_match_options(
'%^(?:[0-9]*x?[0-9]*)?/([0-9]+)$%'
);
foreach ( (array) $matches_a as $matches ) {
if ( isset( $matches[1] ) and '' !== $matches[1] ) {
return $matches[1];
}
}
return $default_value;
}
/**
* Retrieves the minlength option value from the form-tag.
*
* @param string $default_value Optional default value.
* @return string The option value.
*/
public function get_minlength_option( $default_value = false ) {
$option = $this->get_option( 'minlength', 'int', true );
if ( $option ) {
return $option;
} else {
return $default_value;
}
}
/**
* Retrieves the cols option value from the form-tag.
*
* @param string $default_value Optional default value.
* @return string The option value.
*/
public function get_cols_option( $default_value = false ) {
$option = $this->get_option( 'cols', 'int', true );
if ( $option ) {
return $option;
}
$matches_a = $this->get_all_match_options(
'%^([0-9]*)x([0-9]*)(?:/[0-9]+)?$%'
);
foreach ( (array) $matches_a as $matches ) {
if ( isset( $matches[1] ) and '' !== $matches[1] ) {
return $matches[1];
}
}
return $default_value;
}
/**
* Retrieves the rows option value from the form-tag.
*
* @param string $default_value Optional default value.
* @return string The option value.
*/
public function get_rows_option( $default_value = false ) {
$option = $this->get_option( 'rows', 'int', true );
if ( $option ) {
return $option;
}
$matches_a = $this->get_all_match_options(
'%^([0-9]*)x([0-9]*)(?:/[0-9]+)?$%'
);
foreach ( (array) $matches_a as $matches ) {
if ( isset( $matches[2] ) and '' !== $matches[2] ) {
return $matches[2];
}
}
return $default_value;
}
/**
* Retrieves a date-type option value from the form-tag.
*
* @param string $option_name A date-type option name, such as 'min' or 'max'.
* @return string|bool The option value in YYYY-MM-DD format. False if the
* option does not exist or the date value is invalid.
*/
public function get_date_option( $option_name ) {
$option_value = $this->get_option( $option_name, '', true );
if ( empty( $option_value ) ) {
return false;
}
$date = apply_filters( 'wpcf7_form_tag_date_option',
null,
array( $option_name => $option_value )
);
if ( $date ) {
$date_pattern = '/^([0-9]{4})-([0-9]{2})-([0-9]{2})$/';
if ( preg_match( $date_pattern, $date, $matches )
and checkdate( $matches[2], $matches[3], $matches[1] ) ) {
return $date;
}
} else {
$datetime_obj = date_create_immutable(
preg_replace( '/[_]+/', ' ', $option_value ),
wp_timezone()
);
if ( $datetime_obj ) {
return $datetime_obj->format( 'Y-m-d' );
}
}
return false;
}
/**
* Retrieves the default option value from the form-tag.
*
* @param string|array $default_value Optional default value.
* @param string|array $args Optional options for the option value retrieval.
* @return string|array The option value. If the multiple option is enabled,
* an array of option values.
*/
public function get_default_option( $default_value = '', $args = '' ) {
$args = wp_parse_args( $args, array(
'multiple' => false,
'shifted' => false,
) );
$options = (array) $this->get_option( 'default' );
$values = array();
if ( empty( $options ) ) {
return $args['multiple'] ? $values : $default_value;
}
foreach ( $options as $opt ) {
$opt = sanitize_key( $opt );
if ( 'user_' == substr( $opt, 0, 5 ) and is_user_logged_in() ) {
$primary_props = array( 'user_login', 'user_email', 'user_url' );
$opt = in_array( $opt, $primary_props ) ? $opt : substr( $opt, 5 );
$user = wp_get_current_user();
$user_prop = $user->get( $opt );
if ( ! empty( $user_prop ) ) {
if ( $args['multiple'] ) {
$values[] = $user_prop;
} else {
return $user_prop;
}
}
} elseif ( 'post_meta' === $opt and in_the_loop() ) {
if ( $args['multiple'] ) {
$values = array_merge( $values,
get_post_meta( get_the_ID(), $this->name )
);
} else {
$val = (string) get_post_meta( get_the_ID(), $this->name, true );
if ( strlen( $val ) ) {
return $val;
}
}
} elseif ( 'get' === $opt and isset( $_GET[$this->name] ) ) {
$vals = (array) $_GET[$this->name];
$vals = array_map( 'wpcf7_sanitize_query_var', $vals );
if ( $args['multiple'] ) {
$values = array_merge( $values, $vals );
} else {
$val = isset( $vals[0] ) ? (string) $vals[0] : '';
if ( strlen( $val ) ) {
return $val;
}
}
} elseif ( 'post' === $opt and isset( $_POST[$this->name] ) ) {
$vals = (array) $_POST[$this->name];
$vals = array_map( 'wpcf7_sanitize_query_var', $vals );
if ( $args['multiple'] ) {
$values = array_merge( $values, $vals );
} else {
$val = isset( $vals[0] ) ? (string) $vals[0] : '';
if ( strlen( $val ) ) {
return $val;
}
}
} elseif ( 'shortcode_attr' === $opt ) {
if ( $contact_form = WPCF7_ContactForm::get_current() ) {
$val = $contact_form->shortcode_attr( $this->name );
if ( isset( $val ) and strlen( $val ) ) {
if ( $args['multiple'] ) {
$values[] = $val;
} else {
return $val;
}
}
}
} elseif ( preg_match( '/^[0-9_]+$/', $opt ) ) {
$nums = explode( '_', $opt );
foreach ( $nums as $num ) {
$num = absint( $num );
$num = $args['shifted'] ? $num : $num - 1;
if ( isset( $this->values[$num] ) ) {
if ( $args['multiple'] ) {
$values[] = $this->values[$num];
} else {
return $this->values[$num];
}
}
}
}
}
if ( $args['multiple'] ) {
$values = array_unique( $values );
return $values;
} else {
return $default_value;
}
}
/**
* Retrieves the data option value from the form-tag.
*
* @param string|array $args Optional options for the option value retrieval.
* @return mixed The option value.
*/
public function get_data_option( $args = '' ) {
$options = (array) $this->get_option( 'data' );
return apply_filters( 'wpcf7_form_tag_data_option', null, $options, $args );
}
/**
* Retrieves the limit option value from the form-tag.
*
* @param int $default_value Optional default value. Default 1048576.
* @return int The option value.
*/
public function get_limit_option( $default_value = MB_IN_BYTES ) {
$pattern = '/^limit:([1-9][0-9]*)([kKmM]?[bB])?$/';
$matches = $this->get_first_match_option( $pattern );
if ( $matches ) {
$size = (int) $matches[1];
if ( ! empty( $matches[2] ) ) {
$kbmb = strtolower( $matches[2] );
if ( 'kb' === $kbmb ) {
$size *= KB_IN_BYTES;
} elseif ( 'mb' === $kbmb ) {
$size *= MB_IN_BYTES;
}
}
return $size;
}
return (int) $default_value;
}
/**
* Retrieves the value of the first option matches the given
* regular expression pattern.
*
* @param string $pattern Regular expression pattern.
* @return array|bool Option value as an array of matched strings.
* False if there is no option matches the pattern.
*/
public function get_first_match_option( $pattern ) {
foreach( (array) $this->options as $option ) {
if ( preg_match( $pattern, $option, $matches ) ) {
return $matches;
}
}
return false;
}
/**
* Retrieves values of options that match the given
* regular expression pattern.
*
* @param string $pattern Regular expression pattern.
* @return array Array of arrays of strings that match the pattern.
*/
public function get_all_match_options( $pattern ) {
$result = array();
foreach( (array) $this->options as $option ) {
if ( preg_match( $pattern, $option, $matches ) ) {
$result[] = $matches;
}
}
return $result;
}
/**
* Assigns a value to the specified offset.
*
* @link https://www.php.net/manual/en/arrayaccess.offsetset.php
*/
#[ReturnTypeWillChange]
public function offsetSet( $offset, $value ) {
if ( property_exists( __CLASS__, $offset ) ) {
$this->{$offset} = $value;
}
}
/**
* Returns the value at specified offset.
*
* @link https://www.php.net/manual/en/arrayaccess.offsetget.php
*/
#[ReturnTypeWillChange]
public function offsetGet( $offset ) {
if ( property_exists( __CLASS__, $offset ) ) {
return $this->{$offset};
}
return null;
}
/**
* Returns true if the specified offset exists.
*
* @link https://www.php.net/manual/en/arrayaccess.offsetexists.php
*/
#[ReturnTypeWillChange]
public function offsetExists( $offset ) {
return property_exists( __CLASS__, $offset );
}
/**
* Unsets an offset.
*
* @link https://www.php.net/manual/en/arrayaccess.offsetunset.php
*/
#[ReturnTypeWillChange]
public function offsetUnset( $offset ) {
}
}

View File

@@ -1,590 +0,0 @@
<?php
/**
* Wrapper function of WPCF7_FormTagsManager::add().
*/
function wpcf7_add_form_tag( $tag_types, $callback, $features = '' ) {
$manager = WPCF7_FormTagsManager::get_instance();
return $manager->add( $tag_types, $callback, $features );
}
/**
* Wrapper function of WPCF7_FormTagsManager::remove().
*/
function wpcf7_remove_form_tag( $tag_type ) {
$manager = WPCF7_FormTagsManager::get_instance();
return $manager->remove( $tag_type );
}
/**
* Wrapper function of WPCF7_FormTagsManager::replace_all().
*/
function wpcf7_replace_all_form_tags( $content ) {
$manager = WPCF7_FormTagsManager::get_instance();
return $manager->replace_all( $content );
}
/**
* Wrapper function of WPCF7_ContactForm::scan_form_tags().
*/
function wpcf7_scan_form_tags( $cond = null ) {
$contact_form = WPCF7_ContactForm::get_current();
if ( $contact_form ) {
return $contact_form->scan_form_tags( $cond );
}
return array();
}
/**
* Wrapper function of WPCF7_FormTagsManager::tag_type_supports().
*/
function wpcf7_form_tag_supports( $tag_type, $feature ) {
$manager = WPCF7_FormTagsManager::get_instance();
return $manager->tag_type_supports( $tag_type, $feature );
}
/**
* The singleton instance of this class manages the collection of form-tags.
*/
class WPCF7_FormTagsManager {
private static $instance;
private $tag_types = array();
private $scanned_tags = null; // Tags scanned at the last time of scan()
private $placeholders = array();
private function __construct() {}
/**
* Returns the singleton instance.
*
* @return WPCF7_FormTagsManager The singleton manager.
*/
public static function get_instance() {
if ( empty( self::$instance ) ) {
self::$instance = new self;
}
return self::$instance;
}
/**
* Returns scanned form-tags.
*
* @return array Array of WPCF7_FormTag objects.
*/
public function get_scanned_tags() {
return $this->scanned_tags;
}
/**
* Registers form-tag types to the manager.
*
* @param string|array $tag_types The name of the form-tag type or
* an array of the names.
* @param callable $callback The callback to generates a form control HTML
* for a form-tag in this type.
* @param string|array $features Optional. Features a form-tag
* in this type supports.
*/
public function add( $tag_types, $callback, $features = '' ) {
if ( ! is_callable( $callback ) ) {
return;
}
if ( true === $features ) { // for back-compat
$features = array( 'name-attr' => true );
}
$features = wp_parse_args( $features, array() );
$tag_types = array_filter( array_unique( (array) $tag_types ) );
foreach ( $tag_types as $tag_type ) {
$tag_type = $this->sanitize_tag_type( $tag_type );
if ( ! $this->tag_type_exists( $tag_type ) ) {
$this->tag_types[$tag_type] = array(
'function' => $callback,
'features' => $features,
);
}
}
}
/**
* Returns true if the given tag type exists.
*/
public function tag_type_exists( $tag_type ) {
return isset( $this->tag_types[$tag_type] );
}
/**
* Returns true if the tag type supports the features.
*
* @param string $tag_type The name of the form-tag type.
* @param array|string $features The feature to check or an array of features.
* @return bool True if the form-tag type supports at least one of
* the given features, false otherwise.
*/
public function tag_type_supports( $tag_type, $features ) {
$features = array_filter( (array) $features );
if ( isset( $this->tag_types[$tag_type]['features'] ) ) {
return (bool) array_intersect(
array_keys( array_filter( $this->tag_types[$tag_type]['features'] ) ),
$features
);
}
return false;
}
/**
* Returns form-tag types that support the given features.
*
* @param array|string $features Optional. The feature to check or
* an array of features. Default empty array.
* @param bool $invert Optional. If this value is true, returns form-tag
* types that do not support the given features. Default false.
* @return array An array of form-tag types. If the $features param is empty,
* returns all form-tag types that have been registered.
*/
public function collect_tag_types( $features = array(), $invert = false ) {
$tag_types = array_keys( $this->tag_types );
if ( empty( $features ) ) {
return $tag_types;
}
$output = array();
foreach ( $tag_types as $tag_type ) {
if ( ! $invert && $this->tag_type_supports( $tag_type, $features )
|| $invert && ! $this->tag_type_supports( $tag_type, $features ) ) {
$output[] = $tag_type;
}
}
return $output;
}
/**
* Sanitizes the form-tag type name.
*/
private function sanitize_tag_type( $tag_type ) {
$tag_type = preg_replace( '/[^a-zA-Z0-9_*]+/', '_', $tag_type );
$tag_type = rtrim( $tag_type, '_' );
$tag_type = strtolower( $tag_type );
return $tag_type;
}
/**
* Deregisters the form-tag type.
*/
public function remove( $tag_type ) {
unset( $this->tag_types[$tag_type] );
}
/**
* Normalizes the text content that includes form-tags.
*/
public function normalize( $content ) {
if ( empty( $this->tag_types ) ) {
return $content;
}
$content = preg_replace_callback(
'/' . $this->tag_regex() . '/s',
array( $this, 'normalize_callback' ),
$content
);
return $content;
}
/**
* The callback function used within normalize().
*/
private function normalize_callback( $matches ) {
// allow [[foo]] syntax for escaping a tag
if ( $matches[1] == '['
and $matches[6] == ']' ) {
return $matches[0];
}
$tag = $matches[2];
$attr = trim( preg_replace( '/[\r\n\t ]+/', ' ', $matches[3] ) );
$attr = strtr( $attr, array( '<' => '&lt;', '>' => '&gt;' ) );
$content = trim( $matches[5] );
$content = str_replace( "\n", '<WPPreserveNewline />', $content );
$result = $matches[1] . '[' . $tag
. ( $attr ? ' ' . $attr : '' )
. ( $matches[4] ? ' ' . $matches[4] : '' )
. ']'
. ( $content ? $content . '[/' . $tag . ']' : '' )
. $matches[6];
return $result;
}
/**
* Replace all form-tags in the given text with placeholders.
*/
public function replace_with_placeholders( $content ) {
if ( empty( $this->tag_types ) ) {
return $content;
}
$this->placeholders = array();
$callback = function ( $matches ) {
// Allow [[foo]] syntax for escaping a tag.
if ( '[' === $matches[1] and ']' === $matches[6] ) {
return $matches[0];
}
$tag = $matches[0];
$tag_type = $matches[2];
$block_or_hidden = $this->tag_type_supports(
$tag_type,
array( 'display-block', 'display-hidden' )
);
if ( $block_or_hidden ) {
$placeholder_tag_name = WPCF7_HTMLFormatter::placeholder_block;
} else {
$placeholder_tag_name = WPCF7_HTMLFormatter::placeholder_inline;
}
$placeholder = sprintf(
'<%1$s id="%2$s" />',
$placeholder_tag_name,
sha1( $tag )
);
list( $placeholder ) =
WPCF7_HTMLFormatter::normalize_start_tag( $placeholder );
$this->placeholders[$placeholder] = $tag;
return $placeholder;
};
return preg_replace_callback(
'/' . $this->tag_regex() . '/s',
$callback,
$content
);
}
/**
* Replace placeholders in the given text with original form-tags.
*/
public function restore_from_placeholders( $content ) {
return str_replace(
array_keys( $this->placeholders ),
array_values( $this->placeholders ),
$content
);
}
/**
* Replaces all form-tags in the text content.
*
* @param string $content The text content including form-tags.
* @return string The result of replacements.
*/
public function replace_all( $content ) {
return $this->scan( $content, true );
}
/**
* Scans form-tags in the text content.
*
* @param string $content The text content including form-tags.
* @param bool $replace Optional. Whether scanned form-tags will be
* replaced. Default false.
* @return array|string An array of scanned form-tags if $replace is false.
* Otherwise text that scanned form-tags are replaced.
*/
public function scan( $content, $replace = false ) {
$this->scanned_tags = array();
if ( empty( $this->tag_types ) ) {
if ( $replace ) {
return $content;
} else {
return $this->scanned_tags;
}
}
if ( $replace ) {
$content = preg_replace_callback(
'/' . $this->tag_regex() . '/s',
array( $this, 'replace_callback' ),
$content
);
return $content;
} else {
preg_replace_callback(
'/' . $this->tag_regex() . '/s',
array( $this, 'scan_callback' ),
$content
);
return $this->scanned_tags;
}
}
/**
* Filters form-tags based on a condition array argument.
*
* @param array|string $input The original form-tags collection.
* If it is a string, scans form-tags from it.
* @param array $cond The conditions that filtering will be based on.
* @return array The filtered form-tags collection.
*/
public function filter( $input, $cond ) {
if ( is_array( $input ) ) {
$tags = $input;
} elseif ( is_string( $input ) ) {
$tags = $this->scan( $input );
} else {
$tags = $this->scanned_tags;
}
$cond = wp_parse_args( $cond, array(
'type' => array(),
'basetype' => array(),
'name' => array(),
'feature' => array(),
) );
$cond = array_map( static function ( $c ) {
return array_filter( array_map( 'trim', (array) $c ) );
}, $cond );
$tags = array_filter(
(array) $tags,
function ( $tag ) use ( $cond ) {
$tag = new WPCF7_FormTag( $tag );
if ( $cond['type']
and ! in_array( $tag->type, $cond['type'], true ) ) {
return false;
}
if ( $cond['basetype']
and ! in_array( $tag->basetype, $cond['basetype'], true ) ) {
return false;
}
if ( $cond['name']
and ! in_array( $tag->name, $cond['name'], true ) ) {
return false;
}
foreach ( $cond['feature'] as $feature ) {
if ( '!' === substr( $feature, 0, 1 ) ) { // Negation
$feature = trim( substr( $feature, 1 ) );
if ( $this->tag_type_supports( $tag->type, $feature ) ) {
return false;
}
} else {
if ( ! $this->tag_type_supports( $tag->type, $feature ) ) {
return false;
}
}
}
return true;
}
);
return array_values( $tags );
}
/**
* Returns the regular expression for a form-tag.
*/
private function tag_regex() {
$tagnames = array_keys( $this->tag_types );
$tagregexp = implode( '|', array_map( 'preg_quote', $tagnames ) );
return '(\[?)'
. '\[(' . $tagregexp . ')(?:[\r\n\t ](.*?))?(?:[\r\n\t ](\/))?\]'
. '(?:([^[]*?)\[\/\2\])?'
. '(\]?)';
}
/**
* The callback function for the form-tag replacement.
*/
private function replace_callback( $matches ) {
return $this->scan_callback( $matches, true );
}
/**
* The callback function for the form-tag scanning.
*/
private function scan_callback( $matches, $replace = false ) {
// allow [[foo]] syntax for escaping a tag
if ( $matches[1] == '['
and $matches[6] == ']' ) {
return substr( $matches[0], 1, -1 );
}
$tag_type = $matches[2];
$tag_basetype = trim( $tag_type, '*' );
$attr = $this->parse_atts( $matches[3] );
$scanned_tag = array(
'type' => $tag_type,
'basetype' => $tag_basetype,
'raw_name' => '',
'name' => '',
'options' => array(),
'raw_values' => array(),
'values' => array(),
'pipes' => null,
'labels' => array(),
'attr' => '',
'content' => '',
);
if ( $this->tag_type_supports( $tag_type, 'singular' ) ) {
$tags_in_same_basetype = $this->filter(
$this->scanned_tags,
array( 'basetype' => $tag_basetype )
);
if ( $tags_in_same_basetype ) {
// Another tag in the same base type already exists. Ignore this one.
return $matches[0];
}
}
if ( $this->tag_type_supports( $tag_type, 'name-attr' ) ) {
if ( ! is_array( $attr ) ) {
return $matches[0]; // Invalid form-tag.
}
$scanned_tag['raw_name'] = (string) array_shift( $attr['options'] );
if ( ! wpcf7_is_name( $scanned_tag['raw_name'] ) ) {
return $matches[0]; // Invalid name is used. Ignore this tag.
}
$scanned_tag['name'] = strtr( $scanned_tag['raw_name'], '.', '_' );
}
if ( is_array( $attr ) ) {
$scanned_tag['options'] = (array) $attr['options'];
$scanned_tag['raw_values'] = (array) $attr['values'];
if ( WPCF7_USE_PIPE ) {
$pipes = new WPCF7_Pipes( $scanned_tag['raw_values'] );
$scanned_tag['values'] = $pipes->collect_befores();
$scanned_tag['pipes'] = $pipes;
} else {
$scanned_tag['values'] = $scanned_tag['raw_values'];
}
$scanned_tag['labels'] = $scanned_tag['values'];
} else {
$scanned_tag['attr'] = $attr;
}
$scanned_tag['values'] = array_map( 'trim', $scanned_tag['values'] );
$scanned_tag['labels'] = array_map( 'trim', $scanned_tag['labels'] );
$content = trim( $matches[5] );
$content = preg_replace( "/<br[\r\n\t ]*\/?>$/m", '', $content );
$scanned_tag['content'] = $content;
$scanned_tag = apply_filters( 'wpcf7_form_tag', $scanned_tag, $replace );
$scanned_tag = new WPCF7_FormTag( $scanned_tag );
$this->scanned_tags[] = $scanned_tag;
if ( $replace ) {
$callback = $this->tag_types[$tag_type]['function'];
return $matches[1] . call_user_func( $callback, $scanned_tag ) . $matches[6];
} else {
return $matches[0];
}
}
/**
* Parses the attributes of a form-tag to extract the name,
* options, and values.
*
* @param string $text Attributes of a form-tag.
* @return array|string An associative array of the options and values
* if the input is in the correct syntax,
* otherwise the input text itself.
*/
private function parse_atts( $text ) {
$atts = array( 'options' => array(), 'values' => array() );
$text = preg_replace( "/[\x{00a0}\x{200b}]+/u", " ", $text );
$text = trim( $text );
$pattern = '%^([-+*=0-9a-zA-Z:.!?#$&@_/|\%\r\n\t ]*?)((?:[\r\n\t ]*"[^"]*"|[\r\n\t ]*\'[^\']*\')*)$%';
if ( preg_match( $pattern, $text, $matches ) ) {
if ( ! empty( $matches[1] ) ) {
$atts['options'] = preg_split( '/[\r\n\t ]+/', trim( $matches[1] ) );
}
if ( ! empty( $matches[2] ) ) {
preg_match_all( '/"[^"]*"|\'[^\']*\'/', $matches[2], $matched_values );
$atts['values'] = wpcf7_strip_quote_deep( $matched_values[0] );
}
} else {
$atts = $text;
}
return $atts;
}
}

View File

@@ -1,569 +0,0 @@
<?php
/**
* Replaces double line breaks with paragraph elements.
*
* @param string $input The text which has to be formatted.
* @param bool $br Optional. If set, this will convert all remaining
* line breaks after paragraphing. Default true.
* @return string Text which has been converted into correct paragraph tags.
*/
function wpcf7_autop( $input, $br = true ) {
$placeholders = array();
// Replace non-HTML embedded elements with placeholders.
$input = preg_replace_callback(
'/<(math|svg).*?<\/\1>/is',
static function ( $matches ) use ( &$placeholders ) {
$placeholder = sprintf(
'<%1$s id="%2$s" />',
WPCF7_HTMLFormatter::placeholder_inline,
sha1( $matches[0] )
);
list( $placeholder ) =
WPCF7_HTMLFormatter::normalize_start_tag( $placeholder );
$placeholders[$placeholder] = $matches[0];
return $placeholder;
},
$input
);
$formatter = new WPCF7_HTMLFormatter( array(
'auto_br' => $br,
) );
$chunks = $formatter->separate_into_chunks( $input );
$output = $formatter->format( $chunks );
// Restore from placeholders.
$output = str_replace(
array_keys( $placeholders ),
array_values( $placeholders ),
$output
);
return $output;
}
/**
* Newline preservation help function for wpcf7_autop().
*
* @deprecated 5.7 Unnecessary to use any more.
*
* @param array $matches preg_replace_callback() matches array.
* @return string Text including newline placeholders.
*/
function wpcf7_autop_preserve_newline_callback( $matches ) {
return str_replace( "\n", '<WPPreserveNewline />', $matches[0] );
}
/**
* Sanitizes the query variables.
*
* @param string $text Query variable.
* @return string Text sanitized.
*/
function wpcf7_sanitize_query_var( $text ) {
$text = wp_unslash( $text );
$text = wp_check_invalid_utf8( $text );
if ( false !== strpos( $text, '<' ) ) {
$text = wp_pre_kses_less_than( $text );
$text = wp_strip_all_tags( $text );
}
$text = preg_replace( '/%[a-f0-9]{2}/i', '', $text );
$text = preg_replace( '/ +/', ' ', $text );
$text = trim( $text, ' ' );
return $text;
}
/**
* Strips quote characters surrounding the input.
*
* @param string $text Input text.
* @return string Processed output.
*/
function wpcf7_strip_quote( $text ) {
$text = trim( $text );
if ( preg_match( '/^"(.*)"$/s', $text, $matches ) ) {
$text = $matches[1];
} elseif ( preg_match( "/^'(.*)'$/s", $text, $matches ) ) {
$text = $matches[1];
}
return $text;
}
/**
* Navigates through an array, object, or scalar, and
* strips quote characters surrounding the each value.
*
* @param mixed $input The array or string to be processed.
* @return mixed Processed value.
*/
function wpcf7_strip_quote_deep( $input ) {
if ( is_string( $input ) ) {
return wpcf7_strip_quote( $input );
}
if ( is_array( $input ) ) {
$result = array();
foreach ( $input as $key => $text ) {
$result[$key] = wpcf7_strip_quote_deep( $text );
}
return $result;
}
}
/**
* Normalizes newline characters.
*
* @param string $text Input text.
* @param string $to Optional. The newline character that is used in the output.
* @return string Normalized text.
*/
function wpcf7_normalize_newline( $text, $to = "\n" ) {
if ( ! is_string( $text ) ) {
return $text;
}
$nls = array( "\r\n", "\r", "\n" );
if ( ! in_array( $to, $nls ) ) {
return $text;
}
return str_replace( $nls, $to, $text );
}
/**
* Navigates through an array, object, or scalar, and
* normalizes newline characters in the each value.
*
* @param mixed $input The array or string to be processed.
* @param string $to Optional. The newline character that is used in the output.
* @return mixed Processed value.
*/
function wpcf7_normalize_newline_deep( $input, $to = "\n" ) {
if ( is_array( $input ) ) {
$result = array();
foreach ( $input as $key => $text ) {
$result[$key] = wpcf7_normalize_newline_deep( $text, $to );
}
return $result;
}
return wpcf7_normalize_newline( $input, $to );
}
/**
* Strips newline characters.
*
* @param string $text Input text.
* @return string Processed one-line text.
*/
function wpcf7_strip_newline( $text ) {
$text = (string) $text;
$text = str_replace( array( "\r", "\n" ), '', $text );
return trim( $text );
}
/**
* Canonicalizes text.
*
* @param string $text Input text.
* @param string|array|object $args Options.
* @return string Canonicalized text.
*/
function wpcf7_canonicalize( $text, $args = '' ) {
// for back-compat
if ( is_string( $args ) and '' !== $args
and false === strpos( $args, '=' ) ) {
$args = array(
'strto' => $args,
);
}
$args = wp_parse_args( $args, array(
'strto' => 'lower',
'strip_separators' => false,
) );
static $charset = null;
if ( ! isset( $charset ) ) {
$charset = get_option( 'blog_charset' );
$is_utf8 = in_array(
$charset,
array( 'utf8', 'utf-8', 'UTF8', 'UTF-8' )
);
if ( $is_utf8 ) {
$charset = 'UTF-8';
}
}
$text = html_entity_decode( $text, ENT_QUOTES | ENT_HTML5, $charset );
if ( function_exists( 'mb_convert_kana' ) ) {
$text = mb_convert_kana( $text, 'asKV', $charset );
}
if ( $args['strip_separators'] ) {
$text = preg_replace( '/[\r\n\t ]+/', '', $text );
} else {
$text = preg_replace( '/[\r\n\t ]+/', ' ', $text );
}
if ( 'lower' == $args['strto'] ) {
if ( function_exists( 'mb_strtolower' ) ) {
$text = mb_strtolower( $text, $charset );
} else {
$text = strtolower( $text );
}
} elseif ( 'upper' == $args['strto'] ) {
if ( function_exists( 'mb_strtoupper' ) ) {
$text = mb_strtoupper( $text, $charset );
} else {
$text = strtoupper( $text );
}
}
$text = trim( $text );
return $text;
}
/**
* Sanitizes Contact Form 7's form unit-tag.
*
* @param string $tag Unit-tag.
* @return string Sanitized unit-tag.
*/
function wpcf7_sanitize_unit_tag( $tag ) {
$tag = preg_replace( '/[^A-Za-z0-9_-]/', '', $tag );
return $tag;
}
/**
* Converts a file name to one that is not executable as a script.
*
* @param string $filename File name.
* @return string Converted file name.
*/
function wpcf7_antiscript_file_name( $filename ) {
$filename = wp_basename( $filename );
// Apply part of protection logic from sanitize_file_name().
$filename = str_replace(
array(
'?', '[', ']', '/', '\\', '=', '<', '>', ':', ';', ',', "'", '"',
'&', '$', '#', '*', '(', ')', '|', '~', '`', '!', '{', '}',
'%', '+', '', '«', '»', '”', '“', chr( 0 )
),
'',
$filename
);
$filename = preg_replace( '/[\r\n\t -]+/', '-', $filename );
$filename = preg_replace( '/[\pC\pZ]+/iu', '', $filename );
$parts = explode( '.', $filename );
if ( count( $parts ) < 2 ) {
return $filename;
}
$script_pattern = '/^(php|phtml|pl|py|rb|cgi|asp|aspx)\d?$/i';
$filename = array_shift( $parts );
$extension = array_pop( $parts );
foreach ( (array) $parts as $part ) {
if ( preg_match( $script_pattern, $part ) ) {
$filename .= '.' . $part . '_';
} else {
$filename .= '.' . $part;
}
}
if ( preg_match( $script_pattern, $extension ) ) {
$filename .= '.' . $extension . '_.txt';
} else {
$filename .= '.' . $extension;
}
return $filename;
}
/**
* Masks a password with asterisks (*).
*
* @param int $right Length of right-hand unmasked text. Default 0.
* @param int $left Length of left-hand unmasked text. Default 0.
* @return string Text of masked password.
*/
function wpcf7_mask_password( $text, $right = 0, $left = 0 ) {
$length = strlen( $text );
$right = absint( $right );
$left = absint( $left );
if ( $length < $right + $left ) {
$right = $left = 0;
}
if ( $length <= 48 ) {
$masked = str_repeat( '*', $length - ( $right + $left ) );
} elseif ( $right + $left < 48 ) {
$masked = str_repeat( '*', 48 - ( $right + $left ) );
} else {
$masked = '****';
}
$left_unmasked = $left ? substr( $text, 0, $left ) : '';
$right_unmasked = $right ? substr( $text, -1 * $right ) : '';
$text = $left_unmasked . $masked . $right_unmasked;
return $text;
}
/**
* Returns an array of allowed HTML tags and attributes for a given context.
*
* @param string $context Context used to decide allowed tags and attributes.
* @return array Array of allowed HTML tags and their allowed attributes.
*/
function wpcf7_kses_allowed_html( $context = 'form' ) {
static $allowed_tags = array();
if ( isset( $allowed_tags[$context] ) ) {
return apply_filters(
'wpcf7_kses_allowed_html',
$allowed_tags[$context],
$context
);
}
$allowed_tags[$context] = wp_kses_allowed_html( 'post' );
if ( 'form' === $context ) {
$additional_tags_for_form = array(
'button' => array(
'disabled' => true,
'name' => true,
'type' => true,
'value' => true,
),
'datalist' => array(),
'fieldset' => array(
'disabled' => true,
'name' => true,
),
'input' => array(
'accept' => true,
'alt' => true,
'capture' => true,
'checked' => true,
'disabled' => true,
'list' => true,
'max' => true,
'maxlength' => true,
'min' => true,
'minlength' => true,
'multiple' => true,
'name' => true,
'placeholder' => true,
'readonly' => true,
'size' => true,
'step' => true,
'type' => true,
'value' => true,
),
'label' => array(
'for' => true,
),
'legend' => array(),
'meter' => array(
'value' => true,
'min' => true,
'max' => true,
'low' => true,
'high' => true,
'optimum' => true,
),
'optgroup' => array(
'disabled' => true,
'label' => true,
),
'option' => array(
'disabled' => true,
'label' => true,
'selected' => true,
'value' => true,
),
'output' => array(
'for' => true,
'name' => true,
),
'progress' => array(
'max' => true,
'value' => true,
),
'select' => array(
'disabled' => true,
'multiple' => true,
'name' => true,
'size' => true,
),
'textarea' => array(
'cols' => true,
'disabled' => true,
'maxlength' => true,
'minlength' => true,
'name' => true,
'placeholder' => true,
'readonly' => true,
'rows' => true,
'spellcheck' => true,
'wrap' => true,
),
);
$additional_tags_for_form = array_map(
static function ( $elm ) {
$global_attributes = array(
'aria-atomic' => true,
'aria-checked' => true,
'aria-describedby' => true,
'aria-details' => true,
'aria-disabled' => true,
'aria-hidden' => true,
'aria-invalid' => true,
'aria-label' => true,
'aria-labelledby' => true,
'aria-live' => true,
'aria-relevant' => true,
'aria-required' => true,
'aria-selected' => true,
'class' => true,
'data-*' => true,
'id' => true,
'inputmode' => true,
'role' => true,
'style' => true,
'tabindex' => true,
'title' => true,
);
return array_merge( $global_attributes, (array) $elm );
},
$additional_tags_for_form
);
$allowed_tags[$context] = array_merge(
$allowed_tags[$context],
$additional_tags_for_form
);
}
return apply_filters(
'wpcf7_kses_allowed_html',
$allowed_tags[$context],
$context
);
}
/**
* Sanitizes content for allowed HTML tags for the specified context.
*
* @param string $input Content to filter.
* @param string $context Context used to decide allowed tags and attributes.
* @return string Filtered text with allowed HTML tags and attributes intact.
*/
function wpcf7_kses( $input, $context = 'form' ) {
$output = wp_kses(
$input,
wpcf7_kses_allowed_html( $context )
);
return $output;
}
/**
* Returns a formatted string of HTML attributes.
*
* @param array $atts Associative array of attribute name and value pairs.
* @return string Formatted HTML attributes.
*/
function wpcf7_format_atts( $atts ) {
$atts_filtered = array();
foreach ( $atts as $name => $value ) {
$name = strtolower( trim( $name ) );
if ( ! preg_match( '/^[a-z_:][a-z_:.0-9-]*$/', $name ) ) {
continue;
}
static $boolean_attributes = array(
'checked',
'disabled',
'inert',
'multiple',
'readonly',
'required',
'selected',
);
if ( in_array( $name, $boolean_attributes ) and '' === $value ) {
$value = false;
}
if ( is_numeric( $value ) ) {
$value = (string) $value;
}
if ( null === $value or false === $value ) {
unset( $atts_filtered[$name] );
} elseif ( true === $value ) {
$atts_filtered[$name] = $name; // boolean attribute
} elseif ( is_string( $value ) ) {
$atts_filtered[$name] = trim( $value );
}
}
$output = '';
foreach ( $atts_filtered as $name => $value ) {
$output .= sprintf( ' %1$s="%2$s"', $name, esc_attr( $value ) );
}
return trim( $output );
}

View File

@@ -1,690 +0,0 @@
<?php
/**
* Returns path to a plugin file.
*
* @param string $path File path relative to the plugin root directory.
* @return string Absolute file path.
*/
function wpcf7_plugin_path( $path = '' ) {
return path_join( WPCF7_PLUGIN_DIR, trim( $path, '/' ) );
}
/**
* Returns the URL to a plugin file.
*
* @param string $path File path relative to the plugin root directory.
* @return string URL.
*/
function wpcf7_plugin_url( $path = '' ) {
$url = plugins_url( $path, WPCF7_PLUGIN );
if ( is_ssl()
and 'http:' == substr( $url, 0, 5 ) ) {
$url = 'https:' . substr( $url, 5 );
}
return $url;
}
/**
* Include a file under WPCF7_PLUGIN_MODULES_DIR.
*
* @param string $path File path relative to the module dir.
* @return bool True on success, false on failure.
*/
function wpcf7_include_module_file( $path ) {
$dir = WPCF7_PLUGIN_MODULES_DIR;
if ( empty( $dir ) or ! is_dir( $dir ) ) {
return false;
}
$path = path_join( $dir, ltrim( $path, '/' ) );
if ( file_exists( $path ) ) {
include_once $path;
return true;
}
return false;
}
/**
* Retrieves uploads directory information.
*
* @param string|bool $type Optional. Type of output. Default false.
* @return array|string Information about the upload directory.
*/
function wpcf7_upload_dir( $type = false ) {
$uploads = wp_get_upload_dir();
$uploads = apply_filters( 'wpcf7_upload_dir', array(
'dir' => $uploads['basedir'],
'url' => $uploads['baseurl'],
) );
if ( 'dir' == $type ) {
return $uploads['dir'];
} if ( 'url' == $type ) {
return $uploads['url'];
}
return $uploads;
}
/**
* Verifies that a correct security nonce was used with time limit.
*
* @param string $nonce Nonce value that was used for verification.
* @param string $action Optional. Context to what is taking place.
* Default 'wp_rest'.
* @return int|bool 1 if the nonce is generated between 0-12 hours ago,
* 2 if the nonce is generated between 12-24 hours ago.
* False if the nonce is invalid.
*/
function wpcf7_verify_nonce( $nonce, $action = 'wp_rest' ) {
return wp_verify_nonce( $nonce, $action );
}
/**
* Creates a cryptographic token tied to a specific action, user, user session,
* and window of time.
*
* @param string $action Optional. Context to what is taking place.
* Default 'wp_rest'.
* @return string The token.
*/
function wpcf7_create_nonce( $action = 'wp_rest' ) {
return wp_create_nonce( $action );
}
/**
* Converts multi-dimensional array to a flat array.
*
* @param mixed $input Array or item of array.
* @return array Flatten array.
*/
function wpcf7_array_flatten( $input ) {
if ( ! is_array( $input ) ) {
return array( $input );
}
$output = array();
foreach ( $input as $value ) {
$output = array_merge( $output, wpcf7_array_flatten( $value ) );
}
return $output;
}
/**
* Excludes unset or blank text values from the given array.
*
* @param array $input The array.
* @return array Array without blank text values.
*/
function wpcf7_exclude_blank( $input ) {
$output = array_filter( $input,
static function ( $i ) {
return isset( $i ) && '' !== $i;
}
);
return array_values( $output );
}
/**
* Creates a comma-separated list from a multi-dimensional array.
*
* @param mixed $input Array or item of array.
* @param string|array $args Optional. Output options.
* @return string Comma-separated list.
*/
function wpcf7_flat_join( $input, $args = '' ) {
$args = wp_parse_args( $args, array(
'separator' => ', ',
) );
$input = wpcf7_array_flatten( $input );
$output = array();
foreach ( (array) $input as $value ) {
if ( is_scalar( $value ) ) {
$output[] = trim( (string) $value );
}
}
return implode( $args['separator'], $output );
}
/**
* Returns true if HTML5 is supported.
*/
function wpcf7_support_html5() {
return (bool) wpcf7_apply_filters_deprecated(
'wpcf7_support_html5',
array( true ),
'5.6',
''
);
}
/**
* Returns true if HTML5 fallback is active.
*/
function wpcf7_support_html5_fallback() {
return (bool) apply_filters( 'wpcf7_support_html5_fallback', false );
}
/**
* Returns true if the Really Simple CAPTCHA plugin is used for contact forms.
*/
function wpcf7_use_really_simple_captcha() {
return apply_filters( 'wpcf7_use_really_simple_captcha',
WPCF7_USE_REALLY_SIMPLE_CAPTCHA
);
}
/**
* Returns true if config validation is active.
*/
function wpcf7_validate_configuration() {
return apply_filters( 'wpcf7_validate_configuration',
WPCF7_VALIDATE_CONFIGURATION
);
}
/**
* Returns true if wpcf7_autop() is applied.
*/
function wpcf7_autop_or_not() {
return (bool) apply_filters( 'wpcf7_autop_or_not', WPCF7_AUTOP );
}
/**
* Returns true if JavaScript for this plugin is loaded.
*/
function wpcf7_load_js() {
return apply_filters( 'wpcf7_load_js', WPCF7_LOAD_JS );
}
/**
* Returns true if CSS for this plugin is loaded.
*/
function wpcf7_load_css() {
return apply_filters( 'wpcf7_load_css', WPCF7_LOAD_CSS );
}
/**
* Builds an HTML anchor element.
*
* @param string $url Link URL.
* @param string $anchor_text Anchor label text.
* @param string|array $args Optional. Link options.
* @return string Formatted anchor element.
*/
function wpcf7_link( $url, $anchor_text, $args = '' ) {
$args = wp_parse_args( $args, array(
'id' => null,
'class' => null,
) );
$atts = array_merge( $args, array(
'href' => esc_url( $url ),
) );
return sprintf(
'<a %1$s>%2$s</a>',
wpcf7_format_atts( $atts ),
esc_html( $anchor_text )
);
}
/**
* Returns the current request URL.
*/
function wpcf7_get_request_uri() {
static $request_uri = '';
if ( empty( $request_uri ) ) {
$request_uri = add_query_arg( array() );
}
return sanitize_url( $request_uri );
}
/**
* Registers post types used for this plugin.
*/
function wpcf7_register_post_types() {
if ( class_exists( 'WPCF7_ContactForm' ) ) {
WPCF7_ContactForm::register_post_type();
return true;
} else {
return false;
}
}
/**
* Returns the version string of this plugin.
*
* @param string|array $args Optional. Output options.
* @return string Version string.
*/
function wpcf7_version( $args = '' ) {
$defaults = array(
'limit' => -1,
'only_major' => false,
);
$args = wp_parse_args( $args, $defaults );
if ( $args['only_major'] ) {
$args['limit'] = 2;
}
$args['limit'] = (int) $args['limit'];
$ver = WPCF7_VERSION;
$ver = strtr( $ver, '_-+', '...' );
$ver = preg_replace( '/[^0-9.]+/', ".$0.", $ver );
$ver = preg_replace( '/[.]+/', ".", $ver );
$ver = trim( $ver, '.' );
$ver = explode( '.', $ver );
if ( -1 < $args['limit'] ) {
$ver = array_slice( $ver, 0, $args['limit'] );
}
$ver = implode( '.', $ver );
return $ver;
}
/**
* Returns array entries that match the given version.
*
* @param string $version The version to search for.
* @param array $input Search target array.
* @return array|bool Array of matched entries. False on failure.
*/
function wpcf7_version_grep( $version, array $input ) {
$pattern = '/^' . preg_quote( (string) $version, '/' ) . '(?:\.|$)/';
return preg_grep( $pattern, $input );
}
/**
* Returns an enctype attribute value.
*
* @param string $enctype Enctype value.
* @return string Enctype value. Empty if not a valid enctype.
*/
function wpcf7_enctype_value( $enctype ) {
$enctype = trim( $enctype );
if ( empty( $enctype ) ) {
return '';
}
$valid_enctypes = array(
'application/x-www-form-urlencoded',
'multipart/form-data',
'text/plain',
);
if ( in_array( $enctype, $valid_enctypes ) ) {
return $enctype;
}
$pattern = '%^enctype="(' . implode( '|', $valid_enctypes ) . ')"$%';
if ( preg_match( $pattern, $enctype, $matches ) ) {
return $matches[1]; // for back-compat
}
return '';
}
/**
* Removes directory recursively.
*
* @param string $dir Directory path.
* @return bool True on success, false on failure.
*/
function wpcf7_rmdir_p( $dir ) {
if ( is_file( $dir ) ) {
$file = $dir;
if ( @unlink( $file ) ) {
return true;
}
$stat = stat( $file );
if ( @chmod( $file, $stat['mode'] | 0200 ) ) { // add write for owner
if ( @unlink( $file ) ) {
return true;
}
@chmod( $file, $stat['mode'] );
}
return false;
}
if ( ! is_dir( $dir ) ) {
return false;
}
if ( $handle = opendir( $dir ) ) {
while ( false !== ( $file = readdir( $handle ) ) ) {
if ( $file == "."
or $file == ".." ) {
continue;
}
wpcf7_rmdir_p( path_join( $dir, $file ) );
}
closedir( $handle );
}
if ( false !== ( $files = scandir( $dir ) )
and ! array_diff( $files, array( '.', '..' ) ) ) {
return rmdir( $dir );
}
return false;
}
/**
* Builds a URL-encoded query string.
*
* @link https://developer.wordpress.org/reference/functions/_http_build_query/
*
* @param array $args URL query parameters.
* @param string $key Optional. If specified, used to prefix key name.
* @return string Query string.
*/
function wpcf7_build_query( $args, $key = '' ) {
$sep = '&';
$ret = array();
foreach ( (array) $args as $k => $v ) {
$k = urlencode( $k );
if ( ! empty( $key ) ) {
$k = $key . '%5B' . $k . '%5D';
}
if ( null === $v ) {
continue;
} elseif ( false === $v ) {
$v = '0';
}
if ( is_array( $v ) or is_object( $v ) ) {
array_push( $ret, wpcf7_build_query( $v, $k ) );
} else {
array_push( $ret, $k . '=' . urlencode( $v ) );
}
}
return implode( $sep, $ret );
}
/**
* Returns the number of code units in a string.
*
* @link http://www.w3.org/TR/html5/infrastructure.html#code-unit-length
*
* @param string $text Input string.
* @return int|bool The number of code units, or false if
* mb_convert_encoding is not available.
*/
function wpcf7_count_code_units( $text ) {
static $use_mb = null;
if ( is_null( $use_mb ) ) {
$use_mb = function_exists( 'mb_convert_encoding' );
}
if ( ! $use_mb ) {
return false;
}
$text = (string) $text;
$text = str_replace( "\r\n", "\n", $text );
$encoding = mb_detect_encoding( $text, mb_detect_order(), true );
if ( $encoding ) {
$text = mb_convert_encoding( $text, 'UTF-16', $encoding );
} else {
$text = mb_convert_encoding( $text, 'UTF-16', 'UTF-8' );
}
$byte_count = mb_strlen( $text, '8bit' );
return floor( $byte_count / 2 );
}
/**
* Returns true if WordPress is running on the localhost.
*/
function wpcf7_is_localhost() {
$sitename = wp_parse_url( network_home_url(), PHP_URL_HOST );
return in_array( strtolower( $sitename ), array( 'localhost', '127.0.0.1' ) );
}
/**
* Marks a function as deprecated and informs when it has been used.
*
* @param string $function_name The function that was called.
* @param string $version The version of Contact Form 7 that deprecated
* the function.
* @param string $replacement The function that should have been called.
*/
function wpcf7_deprecated_function( $function_name, $version, $replacement ) {
if ( WP_DEBUG ) {
if ( function_exists( '__' ) ) {
trigger_error(
sprintf(
/* translators: 1: PHP function name, 2: version number, 3: alternative function name */
__( 'Function %1$s is <strong>deprecated</strong> since Contact Form 7 version %2$s! Use %3$s instead.', 'contact-form-7' ),
$function_name, $version, $replacement
),
E_USER_DEPRECATED
);
} else {
trigger_error(
sprintf(
'Function %1$s is <strong>deprecated</strong> since Contact Form 7 version %2$s! Use %3$s instead.',
$function_name, $version, $replacement
),
E_USER_DEPRECATED
);
}
}
}
/**
* Fires functions attached to a deprecated filter hook.
*
* @param string $hook_name The name of the filter hook.
* @param array $args Array of additional function arguments to be
* passed to apply_filters().
* @param string $version The version of Contact Form 7 that deprecated
* the hook.
* @param string $replacement The hook that should have been used.
*/
function wpcf7_apply_filters_deprecated( $hook_name, $args, $version, $replacement = '' ) {
if ( ! has_filter( $hook_name ) ) {
return $args[0];
}
if ( WP_DEBUG and apply_filters( 'deprecated_hook_trigger_error', true ) ) {
if ( $replacement ) {
trigger_error(
sprintf(
/* translators: 1: WordPress hook name, 2: version number, 3: alternative hook name */
__( 'Hook %1$s is <strong>deprecated</strong> since Contact Form 7 version %2$s! Use %3$s instead.', 'contact-form-7' ),
$hook_name,
$version,
$replacement
),
E_USER_DEPRECATED
);
} else {
trigger_error(
sprintf(
/* translators: 1: WordPress hook name, 2: version number */
__( 'Hook %1$s is <strong>deprecated</strong> since Contact Form 7 version %2$s with no alternative available.', 'contact-form-7' ),
$hook_name,
$version
),
E_USER_DEPRECATED
);
}
}
return apply_filters_ref_array( $hook_name, $args );
}
/**
* Marks something as being incorrectly called.
*
* @param string $function_name The function that was called.
* @param string $message A message explaining what has been done incorrectly.
* @param string $version The version of Contact Form 7 where the message
* was added.
*/
function wpcf7_doing_it_wrong( $function_name, $message, $version ) {
if ( WP_DEBUG ) {
if ( function_exists( '__' ) ) {
if ( $version ) {
$version = sprintf(
/* translators: %s: Contact Form 7 version number. */
__( '(This message was added in Contact Form 7 version %s.)', 'contact-form-7' ),
$version
);
}
trigger_error(
sprintf(
/* translators: Developer debugging message. 1: PHP function name, 2: Explanatory message, 3: Contact Form 7 version number. */
__( 'Function %1$s was called incorrectly. %2$s %3$s', 'contact-form-7' ),
$function_name,
$message,
$version
),
E_USER_NOTICE
);
} else {
if ( $version ) {
$version = sprintf(
'(This message was added in Contact Form 7 version %s.)',
$version
);
}
trigger_error(
sprintf(
'Function %1$s was called incorrectly. %2$s %3$s',
$function_name,
$message,
$version
),
E_USER_NOTICE
);
}
}
}
/**
* Triggers an error about a remote HTTP request and response.
*
* @param string $url The resource URL.
* @param array $request Request arguments.
* @param array|WP_Error $response The response or WP_Error on failure.
*/
function wpcf7_log_remote_request( $url, $request, $response ) {
$log = sprintf(
/* translators: 1: response code, 2: message, 3: body, 4: URL */
__( 'HTTP Response: %1$s %2$s %3$s from %4$s', 'contact-form-7' ),
(int) wp_remote_retrieve_response_code( $response ),
wp_remote_retrieve_response_message( $response ),
wp_remote_retrieve_body( $response ),
$url
);
$log = apply_filters( 'wpcf7_log_remote_request',
$log, $url, $request, $response
);
if ( $log ) {
trigger_error( $log );
}
}
/**
* Anonymizes an IP address by masking local part.
*
* @param string $ip_addr The original IP address.
* @return string|bool Anonymized IP address, or false on failure.
*/
function wpcf7_anonymize_ip_addr( $ip_addr ) {
if ( ! function_exists( 'inet_ntop' )
or ! function_exists( 'inet_pton' ) ) {
return $ip_addr;
}
$packed = inet_pton( $ip_addr );
if ( false === $packed ) {
return $ip_addr;
}
if ( 4 == strlen( $packed ) ) { // IPv4
$mask = '255.255.255.0';
} elseif ( 16 == strlen( $packed ) ) { // IPv6
$mask = 'ffff:ffff:ffff:0000:0000:0000:0000:0000';
} else {
return $ip_addr;
}
return inet_ntop( $packed & inet_pton( $mask ) );
}

View File

@@ -1,678 +0,0 @@
<?php
/**
* Contact Form 7's class used for formatting HTML fragments.
*/
class WPCF7_HTMLFormatter {
// HTML component types.
const text = 0;
const start_tag = 1;
const end_tag = 2;
const comment = 3;
/**
* Tag name reserved for a custom HTML element used as a block placeholder.
*/
const placeholder_block = 'placeholder:block';
/**
* Tag name reserved for a custom HTML element used as an inline placeholder.
*/
const placeholder_inline = 'placeholder:inline';
/**
* The void elements in HTML.
*
* @link https://developer.mozilla.org/en-US/docs/Glossary/Void_element
*/
const void_elements = array(
'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input',
'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr',
self::placeholder_block, self::placeholder_inline,
);
/**
* HTML elements that can contain flow content.
*/
const p_parent_elements = array(
'address', 'article', 'aside', 'blockquote', 'body', 'caption',
'dd', 'details', 'dialog', 'div', 'dt', 'fieldset', 'figcaption',
'figure', 'footer', 'form', 'header', 'li', 'main', 'nav',
'section', 'td', 'th',
);
/**
* HTML elements that can be neither the parent nor a child of
* a paragraph element.
*/
const p_nonparent_elements = array(
'colgroup', 'dl', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head',
'hgroup', 'html', 'legend', 'menu', 'ol', 'pre', 'style', 'summary',
'table', 'tbody', 'template', 'tfoot', 'thead', 'title', 'tr', 'ul',
);
/**
* HTML elements in the phrasing content category, plus non-phrasing
* content elements that can be grandchildren of a paragraph element.
*/
const p_child_elements = array(
'a', 'abbr', 'area', 'audio', 'b', 'bdi', 'bdo', 'br', 'button',
'canvas', 'cite', 'code', 'data', 'datalist', 'del', 'dfn',
'em', 'embed', 'i', 'iframe', 'img', 'input', 'ins', 'kbd',
'keygen', 'label', 'link', 'map', 'mark', 'meta',
'meter', 'noscript', 'object', 'output', 'picture', 'progress',
'q', 'ruby', 's', 'samp', 'script', 'select', 'slot', 'small',
'span', 'strong', 'sub', 'sup', 'textarea',
'time', 'u', 'var', 'video', 'wbr',
'optgroup', 'option', 'rp', 'rt', // non-phrasing grandchildren
self::placeholder_inline,
);
/**
* HTML elements that can contain phrasing content.
*/
const br_parent_elements = array(
'a', 'abbr', 'address', 'article', 'aside', 'audio', 'b', 'bdi',
'bdo', 'blockquote', 'button', 'canvas', 'caption', 'cite', 'code',
'data', 'datalist', 'dd', 'del', 'details', 'dfn', 'dialog', 'div',
'dt', 'em', 'fieldset', 'figcaption', 'figure', 'footer', 'form',
'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'i', 'ins', 'kbd',
'label', 'legend', 'li', 'main', 'map', 'mark', 'meter', 'nav',
'noscript', 'object', 'output', 'p', 'progress', 'q', 'rt',
'ruby', 's', 'samp', 'section', 'slot', 'small', 'span', 'strong',
'sub', 'summary', 'sup', 'td', 'th', 'time', 'u', 'var',
'video',
);
// Properties.
private $options = array();
private $stacked_elements = array();
private $output = '';
/**
* Constructor.
*/
public function __construct( $args = '' ) {
$this->options = wp_parse_args( $args, array(
'auto_br' => true,
'auto_indent' => true,
) );
}
/**
* Separates the given text into chunks of HTML. Each chunk must be an
* associative array that includes 'position', 'type', and 'content' keys.
*
* @param string $input Text to be separated into chunks.
* @return iterable Iterable of chunks.
*/
public function separate_into_chunks( $input ) {
$input_bytelength = strlen( $input );
$position = 0;
while ( $position < $input_bytelength ) {
$next_tag = preg_match(
'/(?:<!--.*?-->|<(?:\/?)[a-z].*?>)/is',
$input,
$matches,
PREG_OFFSET_CAPTURE,
$position
);
if ( ! $next_tag ) {
yield array(
'position' => $position,
'type' => self::text,
'content' => substr( $input, $position ),
);
break;
}
$next_tag = $matches[0][0];
$next_tag_position = $matches[0][1];
if ( $position < $next_tag_position ) {
yield array(
'position' => $position,
'type' => self::text,
'content' => substr(
$input,
$position,
$next_tag_position - $position
),
);
}
if ( '<!' === substr( $next_tag, 0, 2 ) ) {
$next_tag_type = self::comment;
} elseif ( '</' === substr( $next_tag, 0, 2 ) ) {
$next_tag_type = self::end_tag;
} else {
$next_tag_type = self::start_tag;
}
yield array(
'position' => $next_tag_position,
'type' => $next_tag_type,
'content' => substr(
$input,
$next_tag_position,
strlen( $next_tag )
),
);
$position = $next_tag_position + strlen( $next_tag );
}
}
/**
* Normalizes content in each chunk. This may change the type and position
* of the chunk.
*
* @param iterable $chunks The original chunks.
* @return iterable Normalized chunks.
*/
public function pre_format( $chunks ) {
$position = 0;
foreach ( $chunks as $chunk ) {
$chunk['position'] = $position;
// Standardize newline characters to "\n".
$chunk['content'] = str_replace(
array( "\r\n", "\r" ), "\n", $chunk['content']
);
if ( $chunk['type'] === self::start_tag ) {
list( $chunk['content'] ) =
self::normalize_start_tag( $chunk['content'] );
// Replace <br /> by a line break.
if (
$this->options['auto_br'] and
preg_match( '/^<br\s*\/?>$/i', $chunk['content'] )
) {
$chunk['type'] = self::text;
$chunk['content'] = "\n";
}
}
yield $chunk;
$position = self::calc_next_position( $chunk );
}
}
/**
* Concatenates neighboring text chunks to create a single chunk.
*
* @param iterable $chunks The original chunks.
* @return iterable Processed chunks.
*/
public function concatenate_texts( $chunks ) {
$position = 0;
$text_left = null;
foreach ( $chunks as $chunk ) {
$chunk['position'] = $position;
if ( $chunk['type'] === self::text ) {
if ( isset( $text_left ) ) {
$text_left['content'] .= $chunk['content'];
} else {
$text_left = $chunk;
}
continue;
}
if ( isset( $text_left ) ) {
yield $text_left;
$chunk['position'] = self::calc_next_position( $text_left );
$text_left = null;
}
yield $chunk;
$position = self::calc_next_position( $chunk );
}
if ( isset( $text_left ) ) {
yield $text_left;
}
}
/**
* Outputs formatted HTML based on the given chunks.
*
* @param iterable $chunks The original chunks.
* @return string Formatted HTML.
*/
public function format( $chunks ) {
$chunks = $this->pre_format( $chunks );
$chunks = $this->concatenate_texts( $chunks );
$this->output = '';
$this->stacked_elements = array();
foreach ( $chunks as $chunk ) {
if ( $chunk['type'] === self::text ) {
$this->append_text( $chunk['content'] );
}
if ( $chunk['type'] === self::start_tag ) {
$this->start_tag( $chunk['content'] );
}
if ( $chunk['type'] === self::end_tag ) {
$this->end_tag( $chunk['content'] );
}
if ( $chunk['type'] === self::comment ) {
$this->append_comment( $chunk['content'] );
}
}
// Close all remaining tags.
$this->close_all_tags();
return $this->output;
}
/**
* Appends a text node content to the output property.
*
* @param string $content Text node content.
*/
public function append_text( $content ) {
if ( $this->is_inside( array( 'pre', 'template' ) ) ) {
$this->output .= $content;
return;
}
if (
empty( $this->stacked_elements ) or
$this->has_parent( 'p' ) or
$this->has_parent( self::p_parent_elements )
) {
// Close <p> if the content starts with multiple line breaks.
if ( preg_match( '/^\s*\n\s*\n\s*/', $content ) ) {
$this->end_tag( 'p' );
}
// Split up the contents into paragraphs, separated by double line breaks.
$paragraphs = preg_split( '/\s*\n\s*\n\s*/', $content );
$paragraphs = array_filter( $paragraphs, static function ( $paragraph ) {
return '' !== trim( $paragraph );
} );
$paragraphs = array_values( $paragraphs );
if ( $paragraphs ) {
if ( $this->is_inside( 'p' ) ) {
$paragraph = array_shift( $paragraphs );
$paragraph = self::normalize_paragraph(
$paragraph,
$this->options['auto_br']
);
$this->output .= $paragraph;
}
foreach ( $paragraphs as $paragraph ) {
$this->start_tag( 'p' );
$paragraph = ltrim( $paragraph );
$paragraph = self::normalize_paragraph(
$paragraph,
$this->options['auto_br']
);
$this->output .= $paragraph;
}
}
// Close <p> if the content ends with multiple line breaks.
if ( preg_match( '/\s*\n\s*\n\s*$/', $content ) ) {
$this->end_tag( 'p' );
}
// Cases where the content is a single line break.
if ( preg_match( '/^\s*\n\s*$/', $content ) ) {
$auto_br = $this->options['auto_br'] && $this->is_inside( 'p' );
$content = self::normalize_paragraph( $content, $auto_br );
$this->output .= $content;
}
} else {
$auto_br = $this->options['auto_br'] &&
$this->has_parent( self::br_parent_elements );
$content = self::normalize_paragraph( $content, $auto_br );
$this->output .= $content;
}
}
/**
* Appends a start tag to the output property.
*
* @param string $tag A start tag.
*/
public function start_tag( $tag ) {
list( $tag, $tag_name ) = self::normalize_start_tag( $tag );
if ( in_array( $tag_name, self::p_child_elements ) ) {
if (
! $this->is_inside( 'p' ) and
! $this->is_inside( self::p_child_elements ) and
! $this->has_parent( self::p_nonparent_elements )
) {
// Open <p> if it does not exist.
$this->start_tag( 'p' );
}
} elseif (
'p' === $tag_name or
in_array( $tag_name, self::p_parent_elements ) or
in_array( $tag_name, self::p_nonparent_elements )
) {
// Close <p> if it exists.
$this->end_tag( 'p' );
}
if ( 'dd' === $tag_name or 'dt' === $tag_name ) {
// Close <dd> and <dt> if closing tag is omitted.
$this->end_tag( 'dd' );
$this->end_tag( 'dt' );
}
if ( 'li' === $tag_name ) {
// Close <li> if closing tag is omitted.
$this->end_tag( 'li' );
}
if ( 'optgroup' === $tag_name ) {
// Close <option> and <optgroup> if closing tag is omitted.
$this->end_tag( 'option' );
$this->end_tag( 'optgroup' );
}
if ( 'option' === $tag_name ) {
// Close <option> if closing tag is omitted.
$this->end_tag( 'option' );
}
if ( 'rp' === $tag_name or 'rt' === $tag_name ) {
// Close <rp> and <rt> if closing tag is omitted.
$this->end_tag( 'rp' );
$this->end_tag( 'rt' );
}
if ( 'td' === $tag_name or 'th' === $tag_name ) {
// Close <td> and <th> if closing tag is omitted.
$this->end_tag( 'td' );
$this->end_tag( 'th' );
}
if ( 'tr' === $tag_name ) {
// Close <tr> if closing tag is omitted.
$this->end_tag( 'tr' );
}
if ( 'tbody' === $tag_name or 'tfoot' === $tag_name ) {
// Close <thead> if closing tag is omitted.
$this->end_tag( 'thead' );
}
if ( 'tfoot' === $tag_name ) {
// Close <tbody> if closing tag is omitted.
$this->end_tag( 'tbody' );
}
if ( ! in_array( $tag_name, self::void_elements ) ) {
array_unshift( $this->stacked_elements, $tag_name );
}
if ( ! in_array( $tag_name, self::p_child_elements ) ) {
if ( '' !== $this->output ) {
$this->output = rtrim( $this->output ) . "\n";
}
if ( $this->options['auto_indent'] ) {
$this->output .= self::indent( count( $this->stacked_elements ) - 1 );
}
}
$this->output .= $tag;
}
/**
* Closes an element and its open descendants at a time.
*
* @param string $tag An end tag.
*/
public function end_tag( $tag ) {
if ( preg_match( '/<\/(.+?)(?:\s|>)/', $tag, $matches ) ) {
$tag_name = strtolower( $matches[1] );
} else {
$tag_name = strtolower( $tag );
}
$stacked_elements = array_values( $this->stacked_elements );
$tag_position = array_search( $tag_name, $stacked_elements );
if ( false === $tag_position ) {
return;
}
// Element groups that make up an indirect nesting structure.
// Descendant can contain ancestors.
static $nesting_families = array(
array(
'ancestors' => array( 'dl', ),
'descendants' => array( 'dd', 'dt', ),
),
array(
'ancestors' => array( 'ol', 'ul', 'menu', ),
'descendants' => array( 'li', ),
),
array(
'ancestors' => array( 'table', ),
'descendants' => array( 'td', 'th', 'tr', 'thead', 'tbody', 'tfoot', ),
),
);
foreach ( $nesting_families as $family ) {
$ancestors = (array) $family['ancestors'];
$descendants = (array) $family['descendants'];
if ( in_array( $tag_name, $descendants ) ) {
$intersect = array_intersect(
$ancestors,
array_slice( $stacked_elements, 0, $tag_position )
);
if ( $intersect ) { // Ancestor appears after descendant.
return;
}
}
}
while ( $element = array_shift( $this->stacked_elements ) ) {
$this->append_end_tag( $element );
if ( $element === $tag_name ) {
break;
}
}
}
/**
* Closes all open tags.
*/
public function close_all_tags() {
while ( $element = array_shift( $this->stacked_elements ) ) {
$this->append_end_tag( $element );
}
}
/**
* Appends an end tag to the output property.
*
* @param string $tag_name Tag name.
*/
public function append_end_tag( $tag_name ) {
if ( ! in_array( $tag_name, self::p_child_elements ) ) {
// Remove unnecessary <br />.
$this->output = preg_replace( '/\s*<br \/>\s*$/', '', $this->output );
$this->output = rtrim( $this->output ) . "\n";
if ( $this->options['auto_indent'] ) {
$this->output .= self::indent( count( $this->stacked_elements ) );
}
}
$this->output .= sprintf( '</%s>', $tag_name );
// Remove trailing <p></p>.
$this->output = preg_replace( '/<p>\s*<\/p>$/', '', $this->output );
}
/**
* Appends an HTML comment to the output property.
*
* @param string $tag An HTML comment.
*/
public function append_comment( $tag ) {
$this->output .= $tag;
}
/**
* Returns true if it is currently inside one of HTML elements specified
* by tag names.
*
* @param string|array $tag_names A tag name or an array of tag names.
*/
public function is_inside( $tag_names ) {
$tag_names = (array) $tag_names;
foreach ( $this->stacked_elements as $element ) {
if ( in_array( $element, $tag_names ) ) {
return true;
}
}
return false;
}
/**
* Returns true if the parent node is one of HTML elements specified
* by tag names.
*
* @param string|array $tag_names A tag name or an array of tag names.
*/
public function has_parent( $tag_names ) {
$tag_names = (array) $tag_names;
$parent = reset( $this->stacked_elements );
if ( false === $parent ) {
return false;
}
return in_array( $parent, $tag_names );
}
/**
* Calculates the position of the next chunk based on the position and
* length of the current chunk.
*
* @param array $chunk An associative array of the current chunk.
* @return int The position of the next chunk.
*/
public static function calc_next_position( $chunk ) {
return $chunk['position'] + strlen( $chunk['content'] );
}
/**
* Outputs a set of tabs to indent.
*
* @param int $level Indentation level.
* @return string A series of tabs.
*/
public static function indent( $level ) {
$level = (int) $level;
if ( 0 < $level ) {
return str_repeat( "\t", $level );
}
return '';
}
/**
* Normalizes a start tag.
*
* @param string $tag A start tag or a tag name.
* @return array An array includes the normalized start tag and tag name.
*/
public static function normalize_start_tag( $tag ) {
if ( preg_match( '/<(.+?)[\s\/>]/', $tag, $matches ) ) {
$tag_name = strtolower( $matches[1] );
} else {
$tag_name = strtolower( $tag );
$tag = sprintf( '<%s>', $tag_name );
}
if ( in_array( $tag_name, self::void_elements ) ) {
// Normalize void element.
$tag = preg_replace( '/\s*\/?>/', ' />', $tag );
}
return array( $tag, $tag_name );
}
/**
* Normalizes a paragraph of text.
*
* @param string $paragraph A paragraph of text.
* @param bool $auto_br Optional. If true, line breaks will be replaced
* by a br element.
* @return string The normalized paragraph.
*/
public static function normalize_paragraph( $paragraph, $auto_br = false ) {
if ( $auto_br ) {
$paragraph = preg_replace( '/\s*\n\s*/', "<br />\n", $paragraph );
}
$paragraph = preg_replace( '/[ ]+/', " ", $paragraph );
return $paragraph;
}
}

View File

@@ -1,430 +0,0 @@
<?php
/**
* Integration API
*
* @link https://contactform7.com/integration-with-external-apis/
*/
class WPCF7_Integration {
private static $instance;
private $services = array();
private $categories = array();
private function __construct() {}
/**
* Returns initially supported service categories.
*
* @return array Service categories.
*/
public static function get_builtin_categories() {
return array(
'spam_protection' => __( 'Spam protection', 'contact-form-7' ),
'email_marketing' => __( 'Email marketing', 'contact-form-7' ),
'payments' => __( 'Payments', 'contact-form-7' ),
);
}
/**
* Returns the singleton instance of this class.
*
* @return WPCF7_Integration The instance.
*/
public static function get_instance() {
if ( empty( self::$instance ) ) {
self::$instance = new self;
self::$instance->categories = self::get_builtin_categories();
}
return self::$instance;
}
/**
* Adds a service to the services list.
*/
public function add_service( $name, WPCF7_Service $service ) {
$name = sanitize_key( $name );
if ( empty( $name )
or isset( $this->services[$name] ) ) {
return false;
}
$this->services[$name] = $service;
}
/**
* Adds a service category to the categories list.
*/
public function add_category( $name, $title ) {
$name = sanitize_key( $name );
if ( empty( $name )
or isset( $this->categories[$name] ) ) {
return false;
}
$this->categories[$name] = $title;
}
/**
* Returns true if a service with the name exists in the services list.
*
* @param string $name The name of service to search.
*/
public function service_exists( $name = '' ) {
if ( '' == $name ) {
return (bool) count( $this->services );
} else {
return isset( $this->services[$name] );
}
}
/**
* Returns a service object with the name.
*
* @param string $name The name of service.
* @return WPCF7_Service|bool The service object if it exists,
* false otherwise.
*/
public function get_service( $name ) {
if ( $this->service_exists( $name ) ) {
return $this->services[$name];
} else {
return false;
}
}
/**
* Prints services list.
*/
public function list_services( $args = '' ) {
$args = wp_parse_args( $args, array(
'include' => array(),
) );
$singular = false;
$services = (array) $this->services;
if ( ! empty( $args['include'] ) ) {
$services = array_intersect_key( $services,
array_flip( (array) $args['include'] )
);
if ( 1 == count( $services ) ) {
$singular = true;
}
}
if ( empty( $services ) ) {
return;
}
$action = wpcf7_current_action();
foreach ( $services as $name => $service ) {
$cats = array_intersect_key( $this->categories,
array_flip( $service->get_categories() )
);
?>
<div class="card<?php echo $service->is_active() ? ' active' : ''; ?>" id="<?php echo esc_attr( $name ); ?>">
<?php $service->icon(); ?>
<h2 class="title"><?php echo esc_html( $service->get_title() ); ?></h2>
<div class="infobox">
<?php echo esc_html( implode( ', ', $cats ) ); ?>
</div>
<br class="clear" />
<div class="inside">
<?php
if ( $singular ) {
$service->display( $action );
} else {
$service->display();
}
?>
</div>
</div>
<?php
}
}
}
/**
* Abstract class for services.
*
* Only instances of this class's subclasses are allowed to be
* listed on the Integration page.
*/
abstract class WPCF7_Service {
abstract public function get_title();
abstract public function is_active();
public function get_categories() {
return array();
}
public function icon() {
return '';
}
public function link() {
return '';
}
public function load( $action = '' ) {
}
public function display( $action = '' ) {
}
public function admin_notice( $message = '' ) {
}
}
/**
* Class for services that use OAuth.
*
* While this is not an abstract class, subclassing this class for
* your aim is advised.
*/
class WPCF7_Service_OAuth2 extends WPCF7_Service {
protected $client_id = '';
protected $client_secret = '';
protected $access_token = '';
protected $refresh_token = '';
protected $authorization_endpoint = 'https://example.com/authorization';
protected $token_endpoint = 'https://example.com/token';
public function get_title() {
return '';
}
public function is_active() {
return ! empty( $this->refresh_token );
}
protected function save_data() {
}
protected function reset_data() {
}
protected function get_redirect_uri() {
return admin_url();
}
protected function menu_page_url( $args = '' ) {
return menu_page_url( 'wpcf7-integration', false );
}
public function load( $action = '' ) {
if ( 'auth_redirect' == $action ) {
$code = isset( $_GET['code'] ) ? $_GET['code'] : '';
if ( $code ) {
$this->request_token( $code );
}
if ( ! empty( $this->access_token ) ) {
$message = 'success';
} else {
$message = 'failed';
}
wp_safe_redirect( $this->menu_page_url(
array(
'action' => 'setup',
'message' => $message,
)
) );
exit();
}
}
protected function authorize( $scope = '' ) {
$endpoint = add_query_arg(
array(
'response_type' => 'code',
'client_id' => $this->client_id,
'redirect_uri' => urlencode( $this->get_redirect_uri() ),
'scope' => $scope,
),
$this->authorization_endpoint
);
if ( wp_redirect( sanitize_url( $endpoint ) ) ) {
exit();
}
}
protected function get_http_authorization_header( $scheme = 'basic' ) {
$scheme = strtolower( trim( $scheme ) );
switch ( $scheme ) {
case 'bearer':
return sprintf( 'Bearer %s', $this->access_token );
case 'basic':
default:
return sprintf( 'Basic %s',
base64_encode( $this->client_id . ':' . $this->client_secret )
);
}
}
protected function request_token( $authorization_code ) {
$endpoint = add_query_arg(
array(
'code' => $authorization_code,
'redirect_uri' => urlencode( $this->get_redirect_uri() ),
'grant_type' => 'authorization_code',
),
$this->token_endpoint
);
$request = array(
'headers' => array(
'Authorization' => $this->get_http_authorization_header( 'basic' ),
),
);
$response = wp_remote_post( sanitize_url( $endpoint ), $request );
$response_code = (int) wp_remote_retrieve_response_code( $response );
$response_body = wp_remote_retrieve_body( $response );
$response_body = json_decode( $response_body, true );
if ( WP_DEBUG and 400 <= $response_code ) {
$this->log( $endpoint, $request, $response );
}
if ( 401 == $response_code ) { // Unauthorized
$this->access_token = null;
$this->refresh_token = null;
} else {
if ( isset( $response_body['access_token'] ) ) {
$this->access_token = $response_body['access_token'];
} else {
$this->access_token = null;
}
if ( isset( $response_body['refresh_token'] ) ) {
$this->refresh_token = $response_body['refresh_token'];
} else {
$this->refresh_token = null;
}
}
$this->save_data();
return $response;
}
protected function refresh_token() {
$endpoint = add_query_arg(
array(
'refresh_token' => $this->refresh_token,
'grant_type' => 'refresh_token',
),
$this->token_endpoint
);
$request = array(
'headers' => array(
'Authorization' => $this->get_http_authorization_header( 'basic' ),
),
);
$response = wp_remote_post( sanitize_url( $endpoint ), $request );
$response_code = (int) wp_remote_retrieve_response_code( $response );
$response_body = wp_remote_retrieve_body( $response );
$response_body = json_decode( $response_body, true );
if ( WP_DEBUG and 400 <= $response_code ) {
$this->log( $endpoint, $request, $response );
}
if ( 401 == $response_code ) { // Unauthorized
$this->access_token = null;
$this->refresh_token = null;
} else {
if ( isset( $response_body['access_token'] ) ) {
$this->access_token = $response_body['access_token'];
} else {
$this->access_token = null;
}
if ( isset( $response_body['refresh_token'] ) ) {
$this->refresh_token = $response_body['refresh_token'];
}
}
$this->save_data();
return $response;
}
protected function remote_request( $url, $request = array() ) {
static $refreshed = false;
$request = wp_parse_args( $request, array() );
$request['headers'] = array_merge(
$request['headers'],
array(
'Authorization' => $this->get_http_authorization_header( 'bearer' ),
)
);
$response = wp_remote_request( sanitize_url( $url ), $request );
if ( 401 === wp_remote_retrieve_response_code( $response )
and ! $refreshed ) {
$this->refresh_token();
$refreshed = true;
$response = $this->remote_request( $url, $request );
}
return $response;
}
protected function log( $url, $request, $response ) {
wpcf7_log_remote_request( $url, $request, $response );
}
}

View File

@@ -1,26 +0,0 @@
( function( $ ) {
$( function() {
var supportHtml5 = ( function() {
var features = {};
var input = document.createElement( 'input' );
var inputTypes = [ 'date' ];
$.each( inputTypes, function( index, value ) {
input.setAttribute( 'type', value );
features[ value ] = input.type !== 'text';
} );
return features;
} )();
if ( ! supportHtml5.date ) {
$( 'input.wpcf7-date[type="date"]' ).each( function() {
$( this ).datepicker( {
dateFormat: 'yy-mm-dd',
minDate: new Date( $( this ).attr( 'min' ) ),
maxDate: new Date( $( this ).attr( 'max' ) )
} );
} );
}
} );
} )( jQuery );

View File

@@ -1,6 +0,0 @@
<?php
return array(
'dependencies' => array(),
'version' => WPCF7_VERSION,
);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,443 +0,0 @@
/*!
* jQuery UI CSS Framework 1.12.1
* http://jqueryui.com
*
* Copyright jQuery Foundation and other contributors
* Released under the MIT license.
* http://jquery.org/license
*
* http://api.jqueryui.com/category/theming/
*
* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana%2CArial%2Csans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=highlight_soft&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=flat&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=glass&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=glass&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=glass&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=glass&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
*/
/* Component containers
----------------------------------*/
.ui-widget {
font-family: Verdana,Arial,sans-serif;
font-size: 1.1em;
}
.ui-widget .ui-widget {
font-size: 1em;
}
.ui-widget input,
.ui-widget select,
.ui-widget textarea,
.ui-widget button {
font-family: Verdana,Arial,sans-serif;
font-size: 1em;
}
.ui-widget.ui-widget-content {
border: 1px solid #d3d3d3;
}
.ui-widget-content {
border: 1px solid #aaaaaa;
background: #ffffff;
color: #222222;
}
.ui-widget-content a {
color: #222222;
}
.ui-widget-header {
border: 1px solid #aaaaaa;
background: #cccccc url("images/ui-bg_highlight-soft_75_cccccc_1x100.png") 50% 50% repeat-x;
color: #222222;
font-weight: bold;
}
.ui-widget-header a {
color: #222222;
}
/* Interaction states
----------------------------------*/
.ui-state-default,
.ui-widget-content .ui-state-default,
.ui-widget-header .ui-state-default,
.ui-button,
/* We use html here because we need a greater specificity to make sure disabled
works properly when clicked or hovered */
html .ui-button.ui-state-disabled:hover,
html .ui-button.ui-state-disabled:active {
border: 1px solid #d3d3d3;
background: #e6e6e6 url("images/ui-bg_glass_75_e6e6e6_1x400.png") 50% 50% repeat-x;
font-weight: normal;
color: #555555;
}
.ui-state-default a,
.ui-state-default a:link,
.ui-state-default a:visited,
a.ui-button,
a:link.ui-button,
a:visited.ui-button,
.ui-button {
color: #555555;
text-decoration: none;
}
.ui-state-hover,
.ui-widget-content .ui-state-hover,
.ui-widget-header .ui-state-hover,
.ui-state-focus,
.ui-widget-content .ui-state-focus,
.ui-widget-header .ui-state-focus,
.ui-button:hover,
.ui-button:focus {
border: 1px solid #999999;
background: #dadada url("images/ui-bg_glass_75_dadada_1x400.png") 50% 50% repeat-x;
font-weight: normal;
color: #212121;
}
.ui-state-hover a,
.ui-state-hover a:hover,
.ui-state-hover a:link,
.ui-state-hover a:visited,
.ui-state-focus a,
.ui-state-focus a:hover,
.ui-state-focus a:link,
.ui-state-focus a:visited,
a.ui-button:hover,
a.ui-button:focus {
color: #212121;
text-decoration: none;
}
.ui-visual-focus {
box-shadow: 0 0 3px 1px rgb(94, 158, 214);
}
.ui-state-active,
.ui-widget-content .ui-state-active,
.ui-widget-header .ui-state-active,
a.ui-button:active,
.ui-button:active,
.ui-button.ui-state-active:hover {
border: 1px solid #aaaaaa;
background: #ffffff url("images/ui-bg_glass_65_ffffff_1x400.png") 50% 50% repeat-x;
font-weight: normal;
color: #212121;
}
.ui-icon-background,
.ui-state-active .ui-icon-background {
border: #aaaaaa;
background-color: #212121;
}
.ui-state-active a,
.ui-state-active a:link,
.ui-state-active a:visited {
color: #212121;
text-decoration: none;
}
/* Interaction Cues
----------------------------------*/
.ui-state-highlight,
.ui-widget-content .ui-state-highlight,
.ui-widget-header .ui-state-highlight {
border: 1px solid #fcefa1;
background: #fbf9ee url("images/ui-bg_glass_55_fbf9ee_1x400.png") 50% 50% repeat-x;
color: #363636;
}
.ui-state-checked {
border: 1px solid #fcefa1;
background: #fbf9ee;
}
.ui-state-highlight a,
.ui-widget-content .ui-state-highlight a,
.ui-widget-header .ui-state-highlight a {
color: #363636;
}
.ui-state-error,
.ui-widget-content .ui-state-error,
.ui-widget-header .ui-state-error {
border: 1px solid #cd0a0a;
background: #fef1ec url("images/ui-bg_glass_95_fef1ec_1x400.png") 50% 50% repeat-x;
color: #cd0a0a;
}
.ui-state-error a,
.ui-widget-content .ui-state-error a,
.ui-widget-header .ui-state-error a {
color: #cd0a0a;
}
.ui-state-error-text,
.ui-widget-content .ui-state-error-text,
.ui-widget-header .ui-state-error-text {
color: #cd0a0a;
}
.ui-priority-primary,
.ui-widget-content .ui-priority-primary,
.ui-widget-header .ui-priority-primary {
font-weight: bold;
}
.ui-priority-secondary,
.ui-widget-content .ui-priority-secondary,
.ui-widget-header .ui-priority-secondary {
opacity: .7;
filter:Alpha(Opacity=70); /* support: IE8 */
font-weight: normal;
}
.ui-state-disabled,
.ui-widget-content .ui-state-disabled,
.ui-widget-header .ui-state-disabled {
opacity: .35;
filter:Alpha(Opacity=35); /* support: IE8 */
background-image: none;
}
.ui-state-disabled .ui-icon {
filter:Alpha(Opacity=35); /* support: IE8 - See #6059 */
}
/* Icons
----------------------------------*/
/* states and images */
.ui-icon {
width: 16px;
height: 16px;
}
.ui-icon,
.ui-widget-content .ui-icon {
background-image: url("images/ui-icons_222222_256x240.png");
}
.ui-widget-header .ui-icon {
background-image: url("images/ui-icons_222222_256x240.png");
}
.ui-state-hover .ui-icon,
.ui-state-focus .ui-icon,
.ui-button:hover .ui-icon,
.ui-button:focus .ui-icon {
background-image: url("images/ui-icons_454545_256x240.png");
}
.ui-state-active .ui-icon,
.ui-button:active .ui-icon {
background-image: url("images/ui-icons_454545_256x240.png");
}
.ui-state-highlight .ui-icon,
.ui-button .ui-state-highlight.ui-icon {
background-image: url("images/ui-icons_2e83ff_256x240.png");
}
.ui-state-error .ui-icon,
.ui-state-error-text .ui-icon {
background-image: url("images/ui-icons_cd0a0a_256x240.png");
}
.ui-button .ui-icon {
background-image: url("images/ui-icons_888888_256x240.png");
}
/* positioning */
.ui-icon-blank { background-position: 16px 16px; }
.ui-icon-caret-1-n { background-position: 0 0; }
.ui-icon-caret-1-ne { background-position: -16px 0; }
.ui-icon-caret-1-e { background-position: -32px 0; }
.ui-icon-caret-1-se { background-position: -48px 0; }
.ui-icon-caret-1-s { background-position: -65px 0; }
.ui-icon-caret-1-sw { background-position: -80px 0; }
.ui-icon-caret-1-w { background-position: -96px 0; }
.ui-icon-caret-1-nw { background-position: -112px 0; }
.ui-icon-caret-2-n-s { background-position: -128px 0; }
.ui-icon-caret-2-e-w { background-position: -144px 0; }
.ui-icon-triangle-1-n { background-position: 0 -16px; }
.ui-icon-triangle-1-ne { background-position: -16px -16px; }
.ui-icon-triangle-1-e { background-position: -32px -16px; }
.ui-icon-triangle-1-se { background-position: -48px -16px; }
.ui-icon-triangle-1-s { background-position: -65px -16px; }
.ui-icon-triangle-1-sw { background-position: -80px -16px; }
.ui-icon-triangle-1-w { background-position: -96px -16px; }
.ui-icon-triangle-1-nw { background-position: -112px -16px; }
.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
.ui-icon-arrow-1-n { background-position: 0 -32px; }
.ui-icon-arrow-1-ne { background-position: -16px -32px; }
.ui-icon-arrow-1-e { background-position: -32px -32px; }
.ui-icon-arrow-1-se { background-position: -48px -32px; }
.ui-icon-arrow-1-s { background-position: -65px -32px; }
.ui-icon-arrow-1-sw { background-position: -80px -32px; }
.ui-icon-arrow-1-w { background-position: -96px -32px; }
.ui-icon-arrow-1-nw { background-position: -112px -32px; }
.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
.ui-icon-arrowthick-1-n { background-position: 1px -48px; }
.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
.ui-icon-arrow-4 { background-position: 0 -80px; }
.ui-icon-arrow-4-diag { background-position: -16px -80px; }
.ui-icon-extlink { background-position: -32px -80px; }
.ui-icon-newwin { background-position: -48px -80px; }
.ui-icon-refresh { background-position: -64px -80px; }
.ui-icon-shuffle { background-position: -80px -80px; }
.ui-icon-transfer-e-w { background-position: -96px -80px; }
.ui-icon-transferthick-e-w { background-position: -112px -80px; }
.ui-icon-folder-collapsed { background-position: 0 -96px; }
.ui-icon-folder-open { background-position: -16px -96px; }
.ui-icon-document { background-position: -32px -96px; }
.ui-icon-document-b { background-position: -48px -96px; }
.ui-icon-note { background-position: -64px -96px; }
.ui-icon-mail-closed { background-position: -80px -96px; }
.ui-icon-mail-open { background-position: -96px -96px; }
.ui-icon-suitcase { background-position: -112px -96px; }
.ui-icon-comment { background-position: -128px -96px; }
.ui-icon-person { background-position: -144px -96px; }
.ui-icon-print { background-position: -160px -96px; }
.ui-icon-trash { background-position: -176px -96px; }
.ui-icon-locked { background-position: -192px -96px; }
.ui-icon-unlocked { background-position: -208px -96px; }
.ui-icon-bookmark { background-position: -224px -96px; }
.ui-icon-tag { background-position: -240px -96px; }
.ui-icon-home { background-position: 0 -112px; }
.ui-icon-flag { background-position: -16px -112px; }
.ui-icon-calendar { background-position: -32px -112px; }
.ui-icon-cart { background-position: -48px -112px; }
.ui-icon-pencil { background-position: -64px -112px; }
.ui-icon-clock { background-position: -80px -112px; }
.ui-icon-disk { background-position: -96px -112px; }
.ui-icon-calculator { background-position: -112px -112px; }
.ui-icon-zoomin { background-position: -128px -112px; }
.ui-icon-zoomout { background-position: -144px -112px; }
.ui-icon-search { background-position: -160px -112px; }
.ui-icon-wrench { background-position: -176px -112px; }
.ui-icon-gear { background-position: -192px -112px; }
.ui-icon-heart { background-position: -208px -112px; }
.ui-icon-star { background-position: -224px -112px; }
.ui-icon-link { background-position: -240px -112px; }
.ui-icon-cancel { background-position: 0 -128px; }
.ui-icon-plus { background-position: -16px -128px; }
.ui-icon-plusthick { background-position: -32px -128px; }
.ui-icon-minus { background-position: -48px -128px; }
.ui-icon-minusthick { background-position: -64px -128px; }
.ui-icon-close { background-position: -80px -128px; }
.ui-icon-closethick { background-position: -96px -128px; }
.ui-icon-key { background-position: -112px -128px; }
.ui-icon-lightbulb { background-position: -128px -128px; }
.ui-icon-scissors { background-position: -144px -128px; }
.ui-icon-clipboard { background-position: -160px -128px; }
.ui-icon-copy { background-position: -176px -128px; }
.ui-icon-contact { background-position: -192px -128px; }
.ui-icon-image { background-position: -208px -128px; }
.ui-icon-video { background-position: -224px -128px; }
.ui-icon-script { background-position: -240px -128px; }
.ui-icon-alert { background-position: 0 -144px; }
.ui-icon-info { background-position: -16px -144px; }
.ui-icon-notice { background-position: -32px -144px; }
.ui-icon-help { background-position: -48px -144px; }
.ui-icon-check { background-position: -64px -144px; }
.ui-icon-bullet { background-position: -80px -144px; }
.ui-icon-radio-on { background-position: -96px -144px; }
.ui-icon-radio-off { background-position: -112px -144px; }
.ui-icon-pin-w { background-position: -128px -144px; }
.ui-icon-pin-s { background-position: -144px -144px; }
.ui-icon-play { background-position: 0 -160px; }
.ui-icon-pause { background-position: -16px -160px; }
.ui-icon-seek-next { background-position: -32px -160px; }
.ui-icon-seek-prev { background-position: -48px -160px; }
.ui-icon-seek-end { background-position: -64px -160px; }
.ui-icon-seek-start { background-position: -80px -160px; }
/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
.ui-icon-seek-first { background-position: -80px -160px; }
.ui-icon-stop { background-position: -96px -160px; }
.ui-icon-eject { background-position: -112px -160px; }
.ui-icon-volume-off { background-position: -128px -160px; }
.ui-icon-volume-on { background-position: -144px -160px; }
.ui-icon-power { background-position: 0 -176px; }
.ui-icon-signal-diag { background-position: -16px -176px; }
.ui-icon-signal { background-position: -32px -176px; }
.ui-icon-battery-0 { background-position: -48px -176px; }
.ui-icon-battery-1 { background-position: -64px -176px; }
.ui-icon-battery-2 { background-position: -80px -176px; }
.ui-icon-battery-3 { background-position: -96px -176px; }
.ui-icon-circle-plus { background-position: 0 -192px; }
.ui-icon-circle-minus { background-position: -16px -192px; }
.ui-icon-circle-close { background-position: -32px -192px; }
.ui-icon-circle-triangle-e { background-position: -48px -192px; }
.ui-icon-circle-triangle-s { background-position: -64px -192px; }
.ui-icon-circle-triangle-w { background-position: -80px -192px; }
.ui-icon-circle-triangle-n { background-position: -96px -192px; }
.ui-icon-circle-arrow-e { background-position: -112px -192px; }
.ui-icon-circle-arrow-s { background-position: -128px -192px; }
.ui-icon-circle-arrow-w { background-position: -144px -192px; }
.ui-icon-circle-arrow-n { background-position: -160px -192px; }
.ui-icon-circle-zoomin { background-position: -176px -192px; }
.ui-icon-circle-zoomout { background-position: -192px -192px; }
.ui-icon-circle-check { background-position: -208px -192px; }
.ui-icon-circlesmall-plus { background-position: 0 -208px; }
.ui-icon-circlesmall-minus { background-position: -16px -208px; }
.ui-icon-circlesmall-close { background-position: -32px -208px; }
.ui-icon-squaresmall-plus { background-position: -48px -208px; }
.ui-icon-squaresmall-minus { background-position: -64px -208px; }
.ui-icon-squaresmall-close { background-position: -80px -208px; }
.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
/* Misc visuals
----------------------------------*/
/* Corner radius */
.ui-corner-all,
.ui-corner-top,
.ui-corner-left,
.ui-corner-tl {
border-top-left-radius: 4px;
}
.ui-corner-all,
.ui-corner-top,
.ui-corner-right,
.ui-corner-tr {
border-top-right-radius: 4px;
}
.ui-corner-all,
.ui-corner-bottom,
.ui-corner-left,
.ui-corner-bl {
border-bottom-left-radius: 4px;
}
.ui-corner-all,
.ui-corner-bottom,
.ui-corner-right,
.ui-corner-br {
border-bottom-right-radius: 4px;
}
/* Overlays */
.ui-widget-overlay {
background: #aaaaaa;
opacity: .3;
filter: Alpha(Opacity=30); /* support: IE8 */
}
.ui-widget-shadow {
-webkit-box-shadow: -8px -8px 8px #aaaaaa;
box-shadow: -8px -8px 8px #aaaaaa;
}

View File

@@ -1,156 +0,0 @@
<?php
/**
* Retrieves an associative array of languages to which
* this plugin is translated.
*
* @return array Array of languages.
*/
function wpcf7_l10n() {
static $l10n = array();
if ( ! empty( $l10n ) ) {
return $l10n;
}
if ( ! is_admin() ) {
return $l10n;
}
require_once( ABSPATH . 'wp-admin/includes/translation-install.php' );
$api = translations_api( 'plugins', array(
'slug' => 'contact-form-7',
'version' => WPCF7_VERSION,
) );
if ( is_wp_error( $api )
or empty( $api['translations'] ) ) {
return $l10n;
}
foreach ( (array) $api['translations'] as $translation ) {
if ( ! empty( $translation['language'] )
and ! empty( $translation['english_name'] ) ) {
$l10n[$translation['language']] = $translation['english_name'];
}
}
return $l10n;
}
/**
* Returns true if the given locale code looks valid.
*
* @param string $locale Locale code.
*/
function wpcf7_is_valid_locale( $locale ) {
if ( ! is_string( $locale ) ) {
return false;
}
$pattern = '/^[a-z]{2,3}(?:_[a-zA-Z_]{2,})?$/';
return (bool) preg_match( $pattern, $locale );
}
/**
* Returns true if the given locale is an RTL language.
*/
function wpcf7_is_rtl( $locale = '' ) {
static $rtl_locales = array(
'ar' => 'Arabic',
'ary' => 'Moroccan Arabic',
'azb' => 'South Azerbaijani',
'fa_IR' => 'Persian',
'haz' => 'Hazaragi',
'he_IL' => 'Hebrew',
'ps' => 'Pashto',
'ug_CN' => 'Uighur',
);
if ( empty( $locale )
and function_exists( 'is_rtl' ) ) {
return is_rtl();
}
if ( empty( $locale ) ) {
$locale = determine_locale();
}
return isset( $rtl_locales[$locale] );
}
/**
* Loads a translation file into the plugin's text domain.
*
* @param string $locale Locale code.
* @return bool True on success, false on failure.
*/
function wpcf7_load_textdomain( $locale = '' ) {
$mofile = path_join(
WP_LANG_DIR . '/plugins/',
sprintf( '%s-%s.mo', WPCF7_TEXT_DOMAIN, $locale )
);
return load_textdomain( WPCF7_TEXT_DOMAIN, $mofile, $locale );
}
/**
* Unloads translations for the plugin's text domain.
*
* @param bool $reloadable Whether the text domain can be loaded
* just-in-time again.
* @return bool True on success, false on failure.
*/
function wpcf7_unload_textdomain( $reloadable = false ) {
return unload_textdomain( WPCF7_TEXT_DOMAIN, $reloadable );
}
/**
* Switches translation locale, calls the callback, then switches back
* to the original locale.
*
* @param string $locale Locale code.
* @param callable $callback The callable to be called.
* @param mixed $args Parameters to be passed to the callback.
* @return mixed The return value of the callback.
*/
function wpcf7_switch_locale( $locale, callable $callback, ...$args ) {
static $available_locales = null;
if ( ! isset( $available_locales ) ) {
$available_locales = array_merge(
array( 'en_US' ),
get_available_languages()
);
}
$previous_locale = determine_locale();
$do_switch_locale = (
$locale !== $previous_locale &&
in_array( $locale, $available_locales, true ) &&
in_array( $previous_locale, $available_locales, true )
);
if ( $do_switch_locale ) {
wpcf7_unload_textdomain();
switch_to_locale( $locale );
wpcf7_load_textdomain( $locale );
}
$result = call_user_func( $callback, ...$args );
if ( $do_switch_locale ) {
wpcf7_unload_textdomain( true );
restore_previous_locale();
wpcf7_load_textdomain( $previous_locale );
}
return $result;
}

View File

@@ -1,680 +0,0 @@
<?php
add_filter( 'wpcf7_mail_html_body', 'wpcf7_mail_html_body_autop', 10, 1 );
/**
* Filter callback that applies auto-p to HTML email message body.
*/
function wpcf7_mail_html_body_autop( $body ) {
if ( wpcf7_autop_or_not() ) {
$body = wpcf7_autop( $body );
}
return $body;
}
/**
* Class that represents an attempt to compose and send email.
*/
class WPCF7_Mail {
private static $current = null;
private $name = '';
private $locale = '';
private $template = array();
private $use_html = false;
private $exclude_blank = false;
/**
* Returns the singleton instance of this class.
*/
public static function get_current() {
return self::$current;
}
/**
* Composes and sends email based on the specified template.
*
* @param array $template Array of email template.
* @param string $name Optional name of the template, such as
* 'mail' or 'mail_2'. Default empty string.
* @return bool Whether the email was sent successfully.
*/
public static function send( $template, $name = '' ) {
self::$current = new self( $name, $template );
return self::$current->compose();
}
/**
* The constructor method.
*
* @param string $name The name of the email template.
* Such as 'mail' or 'mail_2'.
* @param array $template Array of email template.
*/
private function __construct( $name, $template ) {
$this->name = trim( $name );
$this->use_html = ! empty( $template['use_html'] );
$this->exclude_blank = ! empty( $template['exclude_blank'] );
$this->template = wp_parse_args( $template, array(
'subject' => '',
'sender' => '',
'body' => '',
'recipient' => '',
'additional_headers' => '',
'attachments' => '',
) );
if ( $submission = WPCF7_Submission::get_instance() ) {
$contact_form = $submission->get_contact_form();
$this->locale = $contact_form->locale();
}
}
/**
* Returns the name of the email template.
*/
public function name() {
return $this->name;
}
/**
* Retrieves a component from the email template.
*
* @param string $component The name of the component.
* @param bool $replace_tags Whether to replace mail-tags
* within the component.
* @return string The text representation of the email component.
*/
public function get( $component, $replace_tags = false ) {
$use_html = ( $this->use_html && 'body' == $component );
$exclude_blank = ( $this->exclude_blank && 'body' == $component );
$template = $this->template;
$component = isset( $template[$component] ) ? $template[$component] : '';
if ( $replace_tags ) {
$component = $this->replace_tags( $component, array(
'html' => $use_html,
'exclude_blank' => $exclude_blank,
) );
if ( $use_html ) {
// Convert <example@example.com> to &lt;example@example.com&gt;.
$component = preg_replace_callback(
'/<(.*?)>/',
static function ( $matches ) {
if ( is_email( $matches[1] ) ) {
return sprintf( '&lt;%s&gt;', $matches[1] );
} else {
return $matches[0];
}
},
$component
);
if ( ! preg_match( '%<html[>\s].*</html>%is', $component ) ) {
$component = $this->htmlize( $component );
}
}
}
return $component;
}
/**
* Creates HTML message body by adding the header and footer.
*
* @param string $body The body part of HTML.
* @return string Formatted HTML.
*/
private function htmlize( $body ) {
if ( $this->locale ) {
$lang_atts = sprintf( ' %s',
wpcf7_format_atts( array(
'dir' => wpcf7_is_rtl( $this->locale ) ? 'rtl' : 'ltr',
'lang' => str_replace( '_', '-', $this->locale ),
) )
);
} else {
$lang_atts = '';
}
$header = apply_filters( 'wpcf7_mail_html_header',
'<!doctype html>
<html xmlns="http://www.w3.org/1999/xhtml"' . $lang_atts . '>
<head>
<title>' . esc_html( $this->get( 'subject', true ) ) . '</title>
</head>
<body>
',
$this
);
$body = apply_filters( 'wpcf7_mail_html_body', $body, $this );
$footer = apply_filters( 'wpcf7_mail_html_footer',
'</body>
</html>',
$this
);
return $header . $body . $footer;
}
/**
* Composes an email message and attempts to send it.
*
* @param bool $send Whether to attempt to send email. Default true.
*/
private function compose( $send = true ) {
$components = array(
'subject' => $this->get( 'subject', true ),
'sender' => $this->get( 'sender', true ),
'body' => $this->get( 'body', true ),
'recipient' => $this->get( 'recipient', true ),
'additional_headers' => $this->get( 'additional_headers', true ),
'attachments' => $this->attachments(),
);
$components = apply_filters( 'wpcf7_mail_components',
$components, wpcf7_get_current_contact_form(), $this
);
if ( ! $send ) {
return $components;
}
$subject = wpcf7_strip_newline( $components['subject'] );
$sender = wpcf7_strip_newline( $components['sender'] );
$recipient = wpcf7_strip_newline( $components['recipient'] );
$body = $components['body'];
$additional_headers = trim( $components['additional_headers'] );
$headers = "From: $sender\n";
if ( $this->use_html ) {
$headers .= "Content-Type: text/html\n";
$headers .= "X-WPCF7-Content-Type: text/html\n";
} else {
$headers .= "X-WPCF7-Content-Type: text/plain\n";
}
if ( $additional_headers ) {
$headers .= $additional_headers . "\n";
}
$attachments = array_filter(
(array) $components['attachments'],
function ( $attachment ) {
$path = path_join( WP_CONTENT_DIR, $attachment );
if ( ! wpcf7_is_file_path_in_content_dir( $path ) ) {
if ( WP_DEBUG ) {
trigger_error(
sprintf(
/* translators: %s: Attachment file path. */
__( 'Failed to attach a file. %s is not in the allowed directory.', 'contact-form-7' ),
$path
),
E_USER_NOTICE
);
}
return false;
}
if ( ! is_readable( $path ) or ! is_file( $path ) ) {
if ( WP_DEBUG ) {
trigger_error(
sprintf(
/* translators: %s: Attachment file path. */
__( 'Failed to attach a file. %s is not a readable file.', 'contact-form-7' ),
$path
),
E_USER_NOTICE
);
}
return false;
}
static $total_size = array();
if ( ! isset( $total_size[$this->name] ) ) {
$total_size[$this->name] = 0;
}
$file_size = (int) @filesize( $path );
if ( 25 * MB_IN_BYTES < $total_size[$this->name] + $file_size ) {
if ( WP_DEBUG ) {
trigger_error(
__( 'Failed to attach a file. The total file size exceeds the limit of 25 megabytes.', 'contact-form-7' ),
E_USER_NOTICE
);
}
return false;
}
$total_size[$this->name] += $file_size;
return true;
}
);
return wp_mail( $recipient, $subject, $body, $headers, $attachments );
}
/**
* Replaces mail-tags within the given text.
*/
public function replace_tags( $content, $args = '' ) {
if ( true === $args ) {
$args = array( 'html' => true );
}
$args = wp_parse_args( $args, array(
'html' => false,
'exclude_blank' => false,
) );
return wpcf7_mail_replace_tags( $content, $args );
}
/**
* Creates an array of attachments based on uploaded files and local files.
*/
private function attachments( $template = null ) {
if ( ! $template ) {
$template = $this->get( 'attachments' );
}
$attachments = array();
if ( $submission = WPCF7_Submission::get_instance() ) {
$uploaded_files = $submission->uploaded_files();
foreach ( (array) $uploaded_files as $name => $paths ) {
if ( false !== strpos( $template, "[{$name}]" ) ) {
$attachments = array_merge( $attachments, (array) $paths );
}
}
}
foreach ( explode( "\n", $template ) as $line ) {
$line = trim( $line );
if ( '' === $line or '[' == substr( $line, 0, 1 ) ) {
continue;
}
$attachments[] = path_join( WP_CONTENT_DIR, $line );
}
if ( $submission = WPCF7_Submission::get_instance() ) {
$attachments = array_merge(
$attachments,
(array) $submission->extra_attachments( $this->name )
);
}
return $attachments;
}
}
/**
* Replaces all mail-tags within the given text content.
*
* @param string $content Text including mail-tags.
* @param string|array $args Optional. Output options.
* @return string Result of replacement.
*/
function wpcf7_mail_replace_tags( $content, $args = '' ) {
$args = wp_parse_args( $args, array(
'html' => false,
'exclude_blank' => false,
) );
if ( is_array( $content ) ) {
foreach ( $content as $key => $value ) {
$content[$key] = wpcf7_mail_replace_tags( $value, $args );
}
return $content;
}
$content = explode( "\n", $content );
foreach ( $content as $num => $line ) {
$line = new WPCF7_MailTaggedText( $line, $args );
$replaced = $line->replace_tags();
if ( $args['exclude_blank'] ) {
$replaced_tags = $line->get_replaced_tags();
if ( empty( $replaced_tags )
or array_filter( $replaced_tags, 'strlen' ) ) {
$content[$num] = $replaced;
} else {
unset( $content[$num] ); // Remove a line.
}
} else {
$content[$num] = $replaced;
}
}
$content = implode( "\n", $content );
return $content;
}
add_action( 'phpmailer_init', 'wpcf7_phpmailer_init', 10, 1 );
/**
* Adds custom properties to the PHPMailer object.
*/
function wpcf7_phpmailer_init( $phpmailer ) {
$custom_headers = $phpmailer->getCustomHeaders();
$phpmailer->clearCustomHeaders();
$wpcf7_content_type = false;
foreach ( (array) $custom_headers as $custom_header ) {
$name = $custom_header[0];
$value = $custom_header[1];
if ( 'X-WPCF7-Content-Type' === $name ) {
$wpcf7_content_type = trim( $value );
} else {
$phpmailer->addCustomHeader( $name, $value );
}
}
if ( 'text/html' === $wpcf7_content_type ) {
$phpmailer->msgHTML( $phpmailer->Body );
} elseif ( 'text/plain' === $wpcf7_content_type ) {
$phpmailer->AltBody = '';
}
}
/**
* Class that represents a single-line text including mail-tags.
*/
class WPCF7_MailTaggedText {
private $html = false;
private $callback = null;
private $content = '';
private $replaced_tags = array();
/**
* The constructor method.
*/
public function __construct( $content, $args = '' ) {
$args = wp_parse_args( $args, array(
'html' => false,
'callback' => null,
) );
$this->html = (bool) $args['html'];
if ( null !== $args['callback']
and is_callable( $args['callback'] ) ) {
$this->callback = $args['callback'];
} elseif ( $this->html ) {
$this->callback = array( $this, 'replace_tags_callback_html' );
} else {
$this->callback = array( $this, 'replace_tags_callback' );
}
$this->content = $content;
}
/**
* Retrieves mail-tags that have been replaced by this instance.
*
* @return array List of mail-tags replaced.
*/
public function get_replaced_tags() {
return $this->replaced_tags;
}
/**
* Replaces mail-tags based on regexp.
*/
public function replace_tags() {
$regex = '/(\[?)\[[\t ]*'
. '([a-zA-Z_][0-9a-zA-Z:._-]*)' // [2] = name
. '((?:[\t ]+"[^"]*"|[\t ]+\'[^\']*\')*)' // [3] = values
. '[\t ]*\](\]?)/';
return preg_replace_callback( $regex, $this->callback, $this->content );
}
/**
* Callback function for replacement. For HTML message body.
*/
private function replace_tags_callback_html( $matches ) {
return $this->replace_tags_callback( $matches, true );
}
/**
* Callback function for replacement.
*/
private function replace_tags_callback( $matches, $html = false ) {
// allow [[foo]] syntax for escaping a tag
if ( $matches[1] == '['
and $matches[4] == ']' ) {
return substr( $matches[0], 1, -1 );
}
$tag = $matches[0];
$tagname = $matches[2];
$values = $matches[3];
$mail_tag = new WPCF7_MailTag( $tag, $tagname, $values );
$field_name = $mail_tag->field_name();
$submission = WPCF7_Submission::get_instance();
$submitted = $submission
? $submission->get_posted_data( $field_name )
: null;
if ( $mail_tag->get_option( 'do_not_heat' ) ) {
$submitted = isset( $_POST[$field_name] )
? wp_unslash( $_POST[$field_name] )
: '';
}
$replaced = $submitted;
if ( null !== $replaced ) {
if ( $format = $mail_tag->get_option( 'format' ) ) {
$replaced = $this->format( $replaced, $format );
}
$replaced = wpcf7_flat_join( $replaced, array(
'separator' => wp_get_list_item_separator(),
) );
if ( $html ) {
$replaced = esc_html( $replaced );
$replaced = wptexturize( $replaced );
}
}
if ( $form_tag = $mail_tag->corresponding_form_tag() ) {
$type = $form_tag->type;
$replaced = apply_filters(
"wpcf7_mail_tag_replaced_{$type}", $replaced,
$submitted, $html, $mail_tag
);
}
$replaced = apply_filters(
'wpcf7_mail_tag_replaced', $replaced,
$submitted, $html, $mail_tag
);
if ( null !== $replaced ) {
$replaced = trim( $replaced );
$this->replaced_tags[$tag] = $replaced;
return $replaced;
}
$special = apply_filters( 'wpcf7_special_mail_tags', null,
$mail_tag->tag_name(), $html, $mail_tag
);
if ( null !== $special ) {
$this->replaced_tags[$tag] = $special;
return $special;
}
return $tag;
}
/**
* Formats string based on the formatting option in the form-tag.
*/
public function format( $original, $format ) {
$original = (array) $original;
foreach ( $original as $key => $value ) {
if ( preg_match( '/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/', $value ) ) {
$datetime = date_create( $value, wp_timezone() );
if ( false !== $datetime ) {
$original[$key] = wp_date( $format, $datetime->getTimestamp() );
}
}
}
return $original;
}
}
/**
* Class that represents a mail-tag.
*/
class WPCF7_MailTag {
private $tag;
private $tagname = '';
private $name = '';
private $options = array();
private $values = array();
private $form_tag = null;
/**
* The constructor method.
*/
public function __construct( $tag, $tagname, $values ) {
$this->tag = $tag;
$this->name = $this->tagname = $tagname;
$this->options = array(
'do_not_heat' => false,
'format' => '',
);
if ( ! empty( $values ) ) {
preg_match_all( '/"[^"]*"|\'[^\']*\'/', $values, $matches );
$this->values = wpcf7_strip_quote_deep( $matches[0] );
}
if ( preg_match( '/^_raw_(.+)$/', $tagname, $matches ) ) {
$this->name = trim( $matches[1] );
$this->options['do_not_heat'] = true;
}
if ( preg_match( '/^_format_(.+)$/', $tagname, $matches ) ) {
$this->name = trim( $matches[1] );
$this->options['format'] = $this->values[0];
}
}
/**
* Returns the name part of this mail-tag.
*/
public function tag_name() {
return $this->tagname;
}
/**
* Returns the form field name corresponding to this mail-tag.
*/
public function field_name() {
return strtr( $this->name, '.', '_' );
}
/**
* Returns the value of the specified option.
*/
public function get_option( $option ) {
return $this->options[$option];
}
/**
* Returns the values part of this mail-tag.
*/
public function values() {
return $this->values;
}
/**
* Retrieves the WPCF7_FormTag object that corresponds to this mail-tag.
*/
public function corresponding_form_tag() {
if ( $this->form_tag instanceof WPCF7_FormTag ) {
return $this->form_tag;
}
if ( $submission = WPCF7_Submission::get_instance() ) {
$contact_form = $submission->get_contact_form();
$tags = $contact_form->scan_form_tags( array(
'name' => $this->field_name(),
'feature' => '! zero-controls-container',
) );
if ( $tags ) {
$this->form_tag = $tags[0];
}
}
return $this->form_tag;
}
}

View File

@@ -1,111 +0,0 @@
<?php
/**
* Pipe-related classes.
*
* @link https://contactform7.com/selectable-recipient-with-pipes/
*/
/**
* Class representing a pair of pipe.
*/
class WPCF7_Pipe {
public $before = '';
public $after = '';
public function __construct( $text ) {
$text = (string) $text;
$pipe_pos = strpos( $text, '|' );
if ( false === $pipe_pos ) {
$this->before = $this->after = trim( $text );
} else {
$this->before = trim( substr( $text, 0, $pipe_pos ) );
$this->after = trim( substr( $text, $pipe_pos + 1 ) );
}
}
}
/**
* Class representing a list of pipes.
*/
class WPCF7_Pipes {
private $pipes = array();
public function __construct( array $texts ) {
foreach ( $texts as $text ) {
$this->add_pipe( $text );
}
}
private function add_pipe( $text ) {
$pipe = new WPCF7_Pipe( $text );
$this->pipes[] = $pipe;
}
public function do_pipe( $input ) {
$input_canonical = wpcf7_canonicalize( $input, array(
'strto' => 'as-is',
) );
foreach ( $this->pipes as $pipe ) {
$before_canonical = wpcf7_canonicalize( $pipe->before, array(
'strto' => 'as-is',
) );
if ( $input_canonical === $before_canonical ) {
return $pipe->after;
}
}
return $input;
}
public function collect_befores() {
$befores = array();
foreach ( $this->pipes as $pipe ) {
$befores[] = $pipe->before;
}
return $befores;
}
public function collect_afters() {
$afters = array();
foreach ( $this->pipes as $pipe ) {
$afters[] = $pipe->after;
}
return $afters;
}
public function zero() {
return empty( $this->pipes );
}
public function random_pipe() {
if ( $this->zero() ) {
return null;
}
return $this->pipes[array_rand( $this->pipes )];
}
public function to_array() {
return array_map(
static function ( WPCF7_Pipe $pipe ) {
return array(
$pipe->before,
$pipe->after,
);
},
$this->pipes
);
}
}

View File

@@ -1,20 +0,0 @@
<?php
/**
* Handy trait provides methods to handle dynamic properties.
*/
trait WPCF7_PocketHolder {
protected $pocket = array();
public function pull( $key ) {
if ( isset( $this->pocket[$key] ) ) {
return $this->pocket[$key];
}
}
public function push( $key, $value ) {
$this->pocket[$key] = $value;
}
}

View File

@@ -1,513 +0,0 @@
<?php
add_action(
'rest_api_init',
static function () {
$controller = new WPCF7_REST_Controller;
$controller->register_routes();
},
10, 0
);
class WPCF7_REST_Controller {
const route_namespace = 'contact-form-7/v1';
public function register_routes() {
register_rest_route( self::route_namespace,
'/contact-forms',
array(
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_contact_forms' ),
'permission_callback' => static function () {
if ( current_user_can( 'wpcf7_read_contact_forms' ) ) {
return true;
} else {
return new WP_Error( 'wpcf7_forbidden',
__( "You are not allowed to access contact forms.", 'contact-form-7' ),
array( 'status' => 403 )
);
}
},
),
array(
'methods' => WP_REST_Server::CREATABLE,
'callback' => array( $this, 'create_contact_form' ),
'permission_callback' => static function () {
if ( current_user_can( 'wpcf7_edit_contact_forms' ) ) {
return true;
} else {
return new WP_Error( 'wpcf7_forbidden',
__( "You are not allowed to create a contact form.", 'contact-form-7' ),
array( 'status' => 403 )
);
}
},
),
)
);
register_rest_route( self::route_namespace,
'/contact-forms/(?P<id>\d+)',
array(
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_contact_form' ),
'permission_callback' => static function ( WP_REST_Request $request ) {
$id = (int) $request->get_param( 'id' );
if ( current_user_can( 'wpcf7_edit_contact_form', $id ) ) {
return true;
} else {
return new WP_Error( 'wpcf7_forbidden',
__( "You are not allowed to access the requested contact form.", 'contact-form-7' ),
array( 'status' => 403 )
);
}
},
),
array(
'methods' => WP_REST_Server::EDITABLE,
'callback' => array( $this, 'update_contact_form' ),
'permission_callback' => static function ( WP_REST_Request $request ) {
$id = (int) $request->get_param( 'id' );
if ( current_user_can( 'wpcf7_edit_contact_form', $id ) ) {
return true;
} else {
return new WP_Error( 'wpcf7_forbidden',
__( "You are not allowed to access the requested contact form.", 'contact-form-7' ),
array( 'status' => 403 )
);
}
},
),
array(
'methods' => WP_REST_Server::DELETABLE,
'callback' => array( $this, 'delete_contact_form' ),
'permission_callback' => static function ( WP_REST_Request $request ) {
$id = (int) $request->get_param( 'id' );
if ( current_user_can( 'wpcf7_delete_contact_form', $id ) ) {
return true;
} else {
return new WP_Error( 'wpcf7_forbidden',
__( "You are not allowed to access the requested contact form.", 'contact-form-7' ),
array( 'status' => 403 )
);
}
},
),
)
);
register_rest_route( self::route_namespace,
'/contact-forms/(?P<id>\d+)/feedback',
array(
array(
'methods' => WP_REST_Server::CREATABLE,
'callback' => array( $this, 'create_feedback' ),
'permission_callback' => '__return_true',
),
)
);
register_rest_route( self::route_namespace,
'/contact-forms/(?P<id>\d+)/feedback/schema',
array(
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_schema' ),
'permission_callback' => '__return_true',
),
'schema' => 'wpcf7_swv_get_meta_schema',
)
);
register_rest_route( self::route_namespace,
'/contact-forms/(?P<id>\d+)/refill',
array(
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_refill' ),
'permission_callback' => '__return_true',
),
)
);
}
public function get_contact_forms( WP_REST_Request $request ) {
$args = array();
$per_page = $request->get_param( 'per_page' );
if ( null !== $per_page ) {
$args['posts_per_page'] = (int) $per_page;
}
$offset = $request->get_param( 'offset' );
if ( null !== $offset ) {
$args['offset'] = (int) $offset;
}
$order = $request->get_param( 'order' );
if ( null !== $order ) {
$args['order'] = (string) $order;
}
$orderby = $request->get_param( 'orderby' );
if ( null !== $orderby ) {
$args['orderby'] = (string) $orderby;
}
$search = $request->get_param( 'search' );
if ( null !== $search ) {
$args['s'] = (string) $search;
}
$items = WPCF7_ContactForm::find( $args );
$response = array();
foreach ( $items as $item ) {
$response[] = array(
'id' => $item->id(),
'hash' => $item->hash(),
'slug' => $item->name(),
'title' => $item->title(),
'locale' => $item->locale(),
);
}
return rest_ensure_response( $response );
}
public function create_contact_form( WP_REST_Request $request ) {
$id = (int) $request->get_param( 'id' );
if ( $id ) {
return new WP_Error( 'wpcf7_post_exists',
__( "Cannot create existing contact form.", 'contact-form-7' ),
array( 'status' => 400 )
);
}
$args = $request->get_params();
$args['id'] = -1; // Create
$context = $request->get_param( 'context' );
$item = wpcf7_save_contact_form( $args, $context );
if ( ! $item ) {
return new WP_Error( 'wpcf7_cannot_save',
__( "There was an error saving the contact form.", 'contact-form-7' ),
array( 'status' => 500 )
);
}
$response = array(
'id' => $item->id(),
'slug' => $item->name(),
'title' => $item->title(),
'locale' => $item->locale(),
'properties' => $this->get_properties( $item ),
'config_errors' => array(),
);
if ( wpcf7_validate_configuration() ) {
$config_validator = new WPCF7_ConfigValidator( $item );
$config_validator->validate();
$response['config_errors'] = $config_validator->collect_error_messages();
if ( 'save' == $context ) {
$config_validator->save();
}
}
return rest_ensure_response( $response );
}
public function get_contact_form( WP_REST_Request $request ) {
$id = (int) $request->get_param( 'id' );
$item = wpcf7_contact_form( $id );
if ( ! $item ) {
return new WP_Error( 'wpcf7_not_found',
__( "The requested contact form was not found.", 'contact-form-7' ),
array( 'status' => 404 )
);
}
$response = array(
'id' => $item->id(),
'slug' => $item->name(),
'title' => $item->title(),
'locale' => $item->locale(),
'properties' => $this->get_properties( $item ),
);
return rest_ensure_response( $response );
}
public function update_contact_form( WP_REST_Request $request ) {
$id = (int) $request->get_param( 'id' );
$item = wpcf7_contact_form( $id );
if ( ! $item ) {
return new WP_Error( 'wpcf7_not_found',
__( "The requested contact form was not found.", 'contact-form-7' ),
array( 'status' => 404 )
);
}
$args = $request->get_params();
$context = $request->get_param( 'context' );
$item = wpcf7_save_contact_form( $args, $context );
if ( ! $item ) {
return new WP_Error( 'wpcf7_cannot_save',
__( "There was an error saving the contact form.", 'contact-form-7' ),
array( 'status' => 500 )
);
}
$response = array(
'id' => $item->id(),
'slug' => $item->name(),
'title' => $item->title(),
'locale' => $item->locale(),
'properties' => $this->get_properties( $item ),
'config_errors' => array(),
);
if ( wpcf7_validate_configuration() ) {
$config_validator = new WPCF7_ConfigValidator( $item );
$config_validator->validate();
$response['config_errors'] = $config_validator->collect_error_messages();
if ( 'save' == $context ) {
$config_validator->save();
}
}
return rest_ensure_response( $response );
}
public function delete_contact_form( WP_REST_Request $request ) {
$id = (int) $request->get_param( 'id' );
$item = wpcf7_contact_form( $id );
if ( ! $item ) {
return new WP_Error( 'wpcf7_not_found',
__( "The requested contact form was not found.", 'contact-form-7' ),
array( 'status' => 404 )
);
}
$result = $item->delete();
if ( ! $result ) {
return new WP_Error( 'wpcf7_cannot_delete',
__( "There was an error deleting the contact form.", 'contact-form-7' ),
array( 'status' => 500 )
);
}
$response = array( 'deleted' => true );
return rest_ensure_response( $response );
}
public function create_feedback( WP_REST_Request $request ) {
$content_type = $request->get_header( 'Content-Type' );
if ( ! str_starts_with( $content_type, 'multipart/form-data' ) ) {
return new WP_Error( 'wpcf7_unsupported_media_type',
__( "The request payload format is not supported.", 'contact-form-7' ),
array( 'status' => 415 )
);
}
$url_params = $request->get_url_params();
$item = null;
if ( ! empty( $url_params['id'] ) ) {
$item = wpcf7_contact_form( $url_params['id'] );
}
if ( ! $item ) {
return new WP_Error( 'wpcf7_not_found',
__( "The requested contact form was not found.", 'contact-form-7' ),
array( 'status' => 404 )
);
}
$unit_tag = wpcf7_sanitize_unit_tag(
$request->get_param( '_wpcf7_unit_tag' )
);
$result = $item->submit();
$response = array_merge( $result, array(
'into' => sprintf( '#%s', $unit_tag ),
'invalid_fields' => array(),
) );
if ( ! empty( $result['invalid_fields'] ) ) {
$invalid_fields = array();
foreach ( (array) $result['invalid_fields'] as $name => $field ) {
if ( ! wpcf7_is_name( $name ) ) {
continue;
}
$name = strtr( $name, '.', '_' );
$invalid_fields[] = array(
'field' => $name,
'message' => $field['reason'],
'idref' => $field['idref'],
'error_id' => sprintf(
'%1$s-ve-%2$s',
$unit_tag,
$name
),
);
}
$response['invalid_fields'] = $invalid_fields;
}
$response = wpcf7_apply_filters_deprecated(
'wpcf7_ajax_json_echo',
array( $response, $result ),
'5.2',
'wpcf7_feedback_response'
);
$response = apply_filters( 'wpcf7_feedback_response', $response, $result );
return rest_ensure_response( $response );
}
public function get_schema( WP_REST_Request $request ) {
$url_params = $request->get_url_params();
$item = null;
if ( ! empty( $url_params['id'] ) ) {
$item = wpcf7_contact_form( $url_params['id'] );
}
if ( ! $item ) {
return new WP_Error( 'wpcf7_not_found',
__( "The requested contact form was not found.", 'contact-form-7' ),
array( 'status' => 404 )
);
}
$schema = $item->get_schema();
$response = isset( $schema ) ? $schema->to_array() : array();
return rest_ensure_response( $response );
}
public function get_refill( WP_REST_Request $request ) {
$id = (int) $request->get_param( 'id' );
$item = wpcf7_contact_form( $id );
if ( ! $item ) {
return new WP_Error( 'wpcf7_not_found',
__( "The requested contact form was not found.", 'contact-form-7' ),
array( 'status' => 404 )
);
}
$response = wpcf7_apply_filters_deprecated(
'wpcf7_ajax_onload',
array( array() ),
'5.2',
'wpcf7_refill_response'
);
$response = apply_filters( 'wpcf7_refill_response', array() );
return rest_ensure_response( $response );
}
private function get_properties( WPCF7_ContactForm $contact_form ) {
$properties = $contact_form->get_properties();
$properties['form'] = array(
'content' => (string) $properties['form'],
'fields' => array_map(
static function ( WPCF7_FormTag $form_tag ) {
return array(
'type' => $form_tag->type,
'basetype' => $form_tag->basetype,
'name' => $form_tag->name,
'options' => $form_tag->options,
'raw_values' => $form_tag->raw_values,
'labels' => $form_tag->labels,
'values' => $form_tag->values,
'pipes' => $form_tag->pipes instanceof WPCF7_Pipes
? $form_tag->pipes->to_array()
: $form_tag->pipes,
'content' => $form_tag->content,
);
},
$contact_form->scan_form_tags()
),
);
$properties['additional_settings'] = array(
'content' => (string) $properties['additional_settings'],
'settings' => array_filter( array_map(
static function ( $setting ) {
$pattern = '/^([a-zA-Z0-9_]+)[\t ]*:(.*)$/';
if ( preg_match( $pattern, $setting, $matches ) ) {
$name = trim( $matches[1] );
$value = trim( $matches[2] );
if ( in_array( $value, array( 'on', 'true' ), true ) ) {
$value = true;
} elseif ( in_array( $value, array( 'off', 'false' ), true ) ) {
$value = false;
}
return array( $name, $value );
}
return false;
},
explode( "\n", $properties['additional_settings'] )
) ),
);
return $properties;
}
private function get_argument_schema() {
return array(
'id' => array(
'description' => __( "Unique identifier for the contact form.", 'contact-form-7' ),
'type' => 'integer',
'required' => true,
),
);
}
}

View File

@@ -1,101 +0,0 @@
<?php
/**
* All the functions and classes in this file are deprecated.
* You should not use them. The functions and classes will be
* removed in a later version.
*/
function wpcf7_add_shortcode( $tag, $callback, $has_name = false ) {
wpcf7_deprecated_function( __FUNCTION__, '4.6', 'wpcf7_add_form_tag' );
return wpcf7_add_form_tag( $tag, $callback, $has_name );
}
function wpcf7_remove_shortcode( $tag ) {
wpcf7_deprecated_function( __FUNCTION__, '4.6', 'wpcf7_remove_form_tag' );
return wpcf7_remove_form_tag( $tag );
}
function wpcf7_do_shortcode( $content ) {
wpcf7_deprecated_function( __FUNCTION__, '4.6',
'wpcf7_replace_all_form_tags' );
return wpcf7_replace_all_form_tags( $content );
}
function wpcf7_scan_shortcode( $cond = null ) {
wpcf7_deprecated_function( __FUNCTION__, '4.6', 'wpcf7_scan_form_tags' );
return wpcf7_scan_form_tags( $cond );
}
class WPCF7_ShortcodeManager {
private static $form_tags_manager;
private function __construct() {}
public static function get_instance() {
wpcf7_deprecated_function( __METHOD__, '4.6',
'WPCF7_FormTagsManager::get_instance' );
self::$form_tags_manager = WPCF7_FormTagsManager::get_instance();
return new self;
}
public function get_scanned_tags() {
wpcf7_deprecated_function( __METHOD__, '4.6',
'WPCF7_FormTagsManager::get_scanned_tags' );
return self::$form_tags_manager->get_scanned_tags();
}
public function add_shortcode( $tag, $callback, $has_name = false ) {
wpcf7_deprecated_function( __METHOD__, '4.6',
'WPCF7_FormTagsManager::add' );
return self::$form_tags_manager->add( $tag, $callback, $has_name );
}
public function remove_shortcode( $tag ) {
wpcf7_deprecated_function( __METHOD__, '4.6',
'WPCF7_FormTagsManager::remove' );
return self::$form_tags_manager->remove( $tag );
}
public function normalize_shortcode( $content ) {
wpcf7_deprecated_function( __METHOD__, '4.6',
'WPCF7_FormTagsManager::normalize' );
return self::$form_tags_manager->normalize( $content );
}
public function do_shortcode( $content, $exec = true ) {
wpcf7_deprecated_function( __METHOD__, '4.6',
'WPCF7_FormTagsManager::replace_all' );
if ( $exec ) {
return self::$form_tags_manager->replace_all( $content );
} else {
return self::$form_tags_manager->scan( $content );
}
}
public function scan_shortcode( $content ) {
wpcf7_deprecated_function( __METHOD__, '4.6',
'WPCF7_FormTagsManager::scan' );
return self::$form_tags_manager->scan( $content );
}
}
class WPCF7_Shortcode extends WPCF7_FormTag {
public function __construct( $tag ) {
wpcf7_deprecated_function( 'WPCF7_Shortcode', '4.6', 'WPCF7_FormTag' );
parent::__construct( $tag );
}
}

View File

@@ -1,248 +0,0 @@
<?php
/**
** Special Mail Tags
** https://contactform7.com/special-mail-tags/
**/
add_filter( 'wpcf7_special_mail_tags', 'wpcf7_special_mail_tag', 10, 4 );
/**
* Returns output string of a special mail-tag.
*
* @param string $output The string to be output.
* @param string $name The tag name of the special mail-tag.
* @param bool $html Whether the mail-tag is used in an HTML content.
* @param WPCF7_MailTag $mail_tag An object representation of the mail-tag.
* @return string Output of the given special mail-tag.
*/
function wpcf7_special_mail_tag( $output, $name, $html, $mail_tag = null ) {
if ( ! $mail_tag instanceof WPCF7_MailTag ) {
wpcf7_doing_it_wrong(
sprintf( '%s()', __FUNCTION__ ),
__( 'The fourth parameter ($mail_tag) must be an instance of the WPCF7_MailTag class.', 'contact-form-7' ),
'5.2.2'
);
}
$name = preg_replace( '/^wpcf7\./', '_', $name ); // for back-compat
$submission = WPCF7_Submission::get_instance();
if ( ! $submission ) {
return $output;
}
if ( '_remote_ip' === $name ) {
if ( $remote_ip = $submission->get_meta( 'remote_ip' ) ) {
return $remote_ip;
} else {
return '';
}
}
if ( '_user_agent' === $name ) {
if ( $user_agent = $submission->get_meta( 'user_agent' ) ) {
return $html ? esc_html( $user_agent ) : $user_agent;
} else {
return '';
}
}
if ( '_url' === $name ) {
if ( $url = $submission->get_meta( 'url' ) ) {
return $url;
} else {
return '';
}
}
if ( '_date' === $name or '_time' === $name ) {
if ( $timestamp = $submission->get_meta( 'timestamp' ) ) {
if ( '_date' === $name ) {
return wp_date( get_option( 'date_format' ), $timestamp );
}
if ( '_time' === $name ) {
return wp_date( get_option( 'time_format' ), $timestamp );
}
}
return '';
}
if ( '_invalid_fields' === $name ) {
return count( $submission->get_invalid_fields() );
}
return $output;
}
add_filter( 'wpcf7_special_mail_tags', 'wpcf7_post_related_smt', 10, 4 );
/**
* Returns output string of a special mail-tag.
*
* @param string $output The string to be output.
* @param string $name The tag name of the special mail-tag.
* @param bool $html Whether the mail-tag is used in an HTML content.
* @param WPCF7_MailTag $mail_tag An object representation of the mail-tag.
* @return string Output of the given special mail-tag.
*/
function wpcf7_post_related_smt( $output, $name, $html, $mail_tag = null ) {
if ( ! $mail_tag instanceof WPCF7_MailTag ) {
wpcf7_doing_it_wrong(
sprintf( '%s()', __FUNCTION__ ),
__( 'The fourth parameter ($mail_tag) must be an instance of the WPCF7_MailTag class.', 'contact-form-7' ),
'5.2.2'
);
}
if ( ! str_starts_with( $name, '_post_' ) ) {
return $output;
}
$submission = WPCF7_Submission::get_instance();
if ( ! $submission ) {
return $output;
}
$post_id = (int) $submission->get_meta( 'container_post_id' );
if ( ! $post_id or ! $post = get_post( $post_id ) ) {
return '';
}
if ( '_post_id' === $name ) {
return (string) $post->ID;
}
if ( '_post_name' === $name ) {
return $post->post_name;
}
if ( '_post_title' === $name ) {
return $html ? esc_html( $post->post_title ) : $post->post_title;
}
if ( '_post_url' === $name ) {
return get_permalink( $post->ID );
}
$user = new WP_User( $post->post_author );
if ( '_post_author' === $name ) {
return $user->display_name;
}
if ( '_post_author_email' === $name ) {
return $user->user_email;
}
return $output;
}
add_filter( 'wpcf7_special_mail_tags', 'wpcf7_site_related_smt', 10, 4 );
/**
* Returns output string of a special mail-tag.
*
* @param string $output The string to be output.
* @param string $name The tag name of the special mail-tag.
* @param bool $html Whether the mail-tag is used in an HTML content.
* @param WPCF7_MailTag $mail_tag An object representation of the mail-tag.
* @return string Output of the given special mail-tag.
*/
function wpcf7_site_related_smt( $output, $name, $html, $mail_tag = null ) {
if ( ! $mail_tag instanceof WPCF7_MailTag ) {
wpcf7_doing_it_wrong(
sprintf( '%s()', __FUNCTION__ ),
__( 'The fourth parameter ($mail_tag) must be an instance of the WPCF7_MailTag class.', 'contact-form-7' ),
'5.2.2'
);
}
$filter = $html ? 'display' : 'raw';
if ( '_site_title' === $name ) {
$output = get_bloginfo( 'name', $filter );
if ( ! $html ) {
$output = wp_specialchars_decode( $output, ENT_QUOTES );
}
return $output;
}
if ( '_site_description' === $name ) {
$output = get_bloginfo( 'description', $filter );
if ( ! $html ) {
$output = wp_specialchars_decode( $output, ENT_QUOTES );
}
return $output;
}
if ( '_site_url' === $name ) {
return get_bloginfo( 'url', $filter );
}
if ( '_site_admin_email' === $name ) {
return get_bloginfo( 'admin_email', $filter );
}
return $output;
}
add_filter( 'wpcf7_special_mail_tags', 'wpcf7_user_related_smt', 10, 4 );
/**
* Returns output string of a special mail-tag.
*
* @param string $output The string to be output.
* @param string $name The tag name of the special mail-tag.
* @param bool $html Whether the mail-tag is used in an HTML content.
* @param WPCF7_MailTag $mail_tag An object representation of the mail-tag.
* @return string Output of the given special mail-tag.
*/
function wpcf7_user_related_smt( $output, $name, $html, $mail_tag = null ) {
if ( ! $mail_tag instanceof WPCF7_MailTag ) {
wpcf7_doing_it_wrong(
sprintf( '%s()', __FUNCTION__ ),
__( 'The fourth parameter ($mail_tag) must be an instance of the WPCF7_MailTag class.', 'contact-form-7' ),
'5.2.2'
);
}
if ( ! str_starts_with( $name, '_user_' ) or '_user_agent' === $name ) {
return $output;
}
$submission = WPCF7_Submission::get_instance();
if ( ! $submission ) {
return $output;
}
$user_id = (int) $submission->get_meta( 'current_user_id' );
if ( ! $user_id ) {
return '';
}
$primary_props = array( 'user_login', 'user_email', 'user_url' );
$opt = ltrim( $name, '_' );
$opt = in_array( $opt, $primary_props ) ? $opt : substr( $opt, 5 );
$user = new WP_User( $user_id );
if ( $user->has_prop( $opt ) ) {
return $user->get( $opt );
}
return '';
}

View File

@@ -1,981 +0,0 @@
<?php
/**
* Class representing contact form submission.
*/
class WPCF7_Submission {
use WPCF7_PocketHolder;
private static $instance;
private $contact_form;
private $status = 'init';
private $posted_data = array();
private $posted_data_hash = null;
private $skip_spam_check = false;
private $uploaded_files = array();
private $extra_attachments = array();
private $skip_mail = false;
private $response = '';
private $invalid_fields = array();
private $meta = array();
private $consent = array();
private $spam_log = array();
private $result_props = array();
/**
* Returns the singleton instance of this class.
*/
public static function get_instance( $contact_form = null, $args = '' ) {
if ( $contact_form instanceof WPCF7_ContactForm ) {
if ( empty( self::$instance ) ) {
self::$instance = new self( $contact_form, $args );
self::$instance->proceed();
return self::$instance;
} else {
return null;
}
} else {
if ( empty( self::$instance ) ) {
return null;
} else {
return self::$instance;
}
}
}
/**
* Returns true if this submission is created via WP REST API.
*/
public static function is_restful() {
return defined( 'REST_REQUEST' ) && REST_REQUEST;
}
/**
* Constructor.
*/
private function __construct( WPCF7_ContactForm $contact_form, $args = '' ) {
$args = wp_parse_args( $args, array(
'skip_mail' => false,
) );
$this->contact_form = $contact_form;
$this->skip_mail = (bool) $args['skip_mail'];
}
/**
* The main logic of submission.
*/
private function proceed() {
$callback = function () {
$contact_form = $this->contact_form;
$this->setup_meta_data();
$this->setup_posted_data();
if ( $this->is( 'init' ) and ! $this->validate() ) {
$this->set_status( 'validation_failed' );
$this->set_response( $contact_form->message( 'validation_error' ) );
}
if ( $this->is( 'init' ) and ! $this->accepted() ) {
$this->set_status( 'acceptance_missing' );
$this->set_response( $contact_form->message( 'accept_terms' ) );
}
if ( $this->is( 'init' ) and $this->spam() ) {
$this->set_status( 'spam' );
$this->set_response( $contact_form->message( 'spam' ) );
}
if ( $this->is( 'init' ) and ! $this->unship_uploaded_files() ) {
$this->set_status( 'validation_failed' );
$this->set_response( $contact_form->message( 'validation_error' ) );
}
if ( $this->is( 'init' ) ) {
$abort = ! $this->before_send_mail();
if ( $abort ) {
if ( $this->is( 'init' ) ) {
$this->set_status( 'aborted' );
}
if ( '' === $this->get_response() ) {
$this->set_response( $contact_form->filter_message(
__( "Sending mail has been aborted.", 'contact-form-7' ) )
);
}
} elseif ( $this->mail() ) {
$this->set_status( 'mail_sent' );
$this->set_response( $contact_form->message( 'mail_sent_ok' ) );
do_action( 'wpcf7_mail_sent', $contact_form );
} else {
$this->set_status( 'mail_failed' );
$this->set_response( $contact_form->message( 'mail_sent_ng' ) );
do_action( 'wpcf7_mail_failed', $contact_form );
}
}
$this->remove_uploaded_files();
};
wpcf7_switch_locale( $this->contact_form->locale(), $callback );
}
/**
* Returns the current status property.
*/
public function get_status() {
return $this->status;
}
/**
* Sets the status property.
*
* @param string $status The status.
*/
public function set_status( $status ) {
if ( preg_match( '/^[a-z][0-9a-z_]+$/', $status ) ) {
$this->status = $status;
return true;
}
return false;
}
/**
* Returns true if the specified status is identical to the current
* status property.
*
* @param string $status The status to compare.
*/
public function is( $status ) {
return $this->status === $status;
}
/**
* Returns an associative array of submission result properties.
*
* @return array Submission result properties.
*/
public function get_result() {
$result = array_merge( $this->result_props, array(
'status' => $this->get_status(),
'message' => $this->get_response(),
) );
if ( $this->is( 'validation_failed' ) ) {
$result['invalid_fields'] = $this->get_invalid_fields();
}
switch ( $this->get_status() ) {
case 'init':
case 'validation_failed':
case 'acceptance_missing':
case 'spam':
$result['posted_data_hash'] = '';
break;
default:
$result['posted_data_hash'] = $this->get_posted_data_hash();
break;
}
$result = apply_filters( 'wpcf7_submission_result', $result, $this );
return $result;
}
/**
* Adds items to the array of submission result properties.
*
* @param string|array|object $args Value to add to result properties.
* @return array Added result properties.
*/
public function add_result_props( $args = '' ) {
$args = wp_parse_args( $args, array() );
$this->result_props = array_merge( $this->result_props, $args );
return $args;
}
/**
* Retrieves the response property.
*
* @return string The current response property value.
*/
public function get_response() {
return $this->response;
}
/**
* Sets the response property.
*
* @param string $response New response property value.
*/
public function set_response( $response ) {
$this->response = $response;
return true;
}
/**
* Retrieves the contact form property.
*
* @return WPCF7_ContactForm A contact form object.
*/
public function get_contact_form() {
return $this->contact_form;
}
/**
* Search an invalid field by field name.
*
* @param string $name The field name.
* @return array|bool An associative array of validation error
* or false when no invalid field.
*/
public function get_invalid_field( $name ) {
if ( isset( $this->invalid_fields[$name] ) ) {
return $this->invalid_fields[$name];
} else {
return false;
}
}
/**
* Retrieves all invalid fields.
*
* @return array Invalid fields.
*/
public function get_invalid_fields() {
return $this->invalid_fields;
}
/**
* Retrieves meta information.
*
* @param string $name Name of the meta information.
* @return string|null The meta information of the given name if it exists,
* null otherwise.
*/
public function get_meta( $name ) {
if ( isset( $this->meta[$name] ) ) {
return $this->meta[$name];
}
}
/**
* Collects meta information about this submission.
*/
private function setup_meta_data() {
$timestamp = time();
$remote_ip = $this->get_remote_ip_addr();
$remote_port = isset( $_SERVER['REMOTE_PORT'] )
? (int) $_SERVER['REMOTE_PORT'] : '';
$user_agent = isset( $_SERVER['HTTP_USER_AGENT'] )
? substr( $_SERVER['HTTP_USER_AGENT'], 0, 254 ) : '';
$url = $this->get_request_url();
$unit_tag = isset( $_POST['_wpcf7_unit_tag'] )
? wpcf7_sanitize_unit_tag( $_POST['_wpcf7_unit_tag'] ) : '';
$container_post_id = isset( $_POST['_wpcf7_container_post'] )
? (int) $_POST['_wpcf7_container_post'] : 0;
$current_user_id = get_current_user_id();
$do_not_store = $this->contact_form->is_true( 'do_not_store' );
$this->meta = array(
'timestamp' => $timestamp,
'remote_ip' => $remote_ip,
'remote_port' => $remote_port,
'user_agent' => $user_agent,
'url' => $url,
'unit_tag' => $unit_tag,
'container_post_id' => $container_post_id,
'current_user_id' => $current_user_id,
'do_not_store' => $do_not_store,
);
return $this->meta;
}
/**
* Retrieves user input data through this submission.
*
* @param string $name Optional field name.
* @return string|array|null The user input of the field, or array of all
* fields values if no field name specified.
*/
public function get_posted_data( $name = '' ) {
if ( ! empty( $name ) ) {
if ( isset( $this->posted_data[$name] ) ) {
return $this->posted_data[$name];
} else {
return null;
}
}
return $this->posted_data;
}
/**
* Retrieves a user input string value through the specified field.
*
* @param string $name Field name.
* @return string The user input. If the input is an array,
* the first item in the array.
*/
public function get_posted_string( $name ) {
$data = $this->get_posted_data( $name );
$data = wpcf7_array_flatten( $data );
if ( empty( $data ) ) {
return '';
}
// Returns the first array item.
return trim( reset( $data ) );
}
/**
* Constructs posted data property based on user input values.
*/
private function setup_posted_data() {
$posted_data = array_filter( (array) $_POST, static function ( $key ) {
return '_' !== substr( $key, 0, 1 );
}, ARRAY_FILTER_USE_KEY );
$posted_data = wp_unslash( $posted_data );
$posted_data = $this->sanitize_posted_data( $posted_data );
$tags = $this->contact_form->scan_form_tags();
foreach ( (array) $tags as $tag ) {
if ( empty( $tag->name ) ) {
continue;
}
$type = $tag->type;
$name = $tag->name;
$pipes = $tag->pipes;
$value_orig = $value = '';
if ( isset( $posted_data[$name] ) ) {
$value_orig = $value = $posted_data[$name];
}
if ( WPCF7_USE_PIPE
and $pipes instanceof WPCF7_Pipes
and ! $pipes->zero() ) {
if ( is_array( $value_orig ) ) {
$value = array();
foreach ( $value_orig as $v ) {
$value[] = $pipes->do_pipe( $v );
}
} else {
$value = $pipes->do_pipe( $value_orig );
}
}
if ( wpcf7_form_tag_supports( $type, 'selectable-values' ) ) {
$value = (array) $value;
if ( $tag->has_option( 'free_text' )
and isset( $posted_data[$name . '_free_text'] ) ) {
$last_val = array_pop( $value );
list( $tied_item ) = array_slice(
WPCF7_USE_PIPE ? $tag->pipes->collect_afters() : $tag->values,
-1, 1
);
list( $last_val, $tied_item ) = array_map(
static function ( $item ) {
return wpcf7_canonicalize( $item, array(
'strto' => 'as-is',
) );
},
array( $last_val, $tied_item )
);
if ( $last_val === $tied_item ) {
$value[] = sprintf( '%s %s',
$last_val,
$posted_data[$name . '_free_text']
);
} else {
$value[] = $last_val;
}
unset( $posted_data[$name . '_free_text'] );
}
}
$value = apply_filters( "wpcf7_posted_data_{$type}", $value,
$value_orig, $tag
);
$posted_data[$name] = $value;
if ( $tag->has_option( 'consent_for:storage' )
and empty( $posted_data[$name] ) ) {
$this->meta['do_not_store'] = true;
}
}
$this->posted_data = apply_filters( 'wpcf7_posted_data', $posted_data );
$this->posted_data_hash = $this->create_posted_data_hash();
return $this->posted_data;
}
/**
* Sanitizes user input data.
*/
private function sanitize_posted_data( $value ) {
if ( is_array( $value ) ) {
$value = array_map( array( $this, 'sanitize_posted_data' ), $value );
} elseif ( is_string( $value ) ) {
$value = wp_check_invalid_utf8( $value );
$value = wp_kses_no_null( $value );
}
return $value;
}
/**
* Returns the time-dependent variable for hash creation.
*
* @return float Float value rounded up to the next highest integer.
*/
private function posted_data_hash_tick() {
return ceil( time() / ( HOUR_IN_SECONDS / 2 ) );
}
/**
* Creates a hash string based on posted data, the remote IP address,
* contact form location, and window of time.
*
* @param string $tick Optional. If not specified, result of
* posted_data_hash_tick() will be used.
* @return string The hash.
*/
private function create_posted_data_hash( $tick = '' ) {
if ( '' === $tick ) {
$tick = $this->posted_data_hash_tick();
}
$hash = wp_hash(
wpcf7_flat_join( array_merge(
array(
$tick,
$this->get_meta( 'remote_ip' ),
$this->get_meta( 'unit_tag' ),
),
$this->posted_data
) ),
'wpcf7_submission'
);
return $hash;
}
/**
* Returns the hash string created for this submission.
*
* @return string The current hash for the submission.
*/
public function get_posted_data_hash() {
return $this->posted_data_hash;
}
/**
* Verifies that the given string is equivalent to the posted data hash.
*
* @param string $hash Optional. This value will be compared to the
* current posted data hash for the submission. If not
* specified, the value of $_POST['_wpcf7_posted_data_hash']
* will be used.
* @return int|bool 1 if $hash is created 0-30 minutes ago,
* 2 if $hash is created 30-60 minutes ago,
* false if $hash is invalid.
*/
public function verify_posted_data_hash( $hash = '' ) {
if ( '' === $hash and ! empty( $_POST['_wpcf7_posted_data_hash'] ) ) {
$hash = trim( $_POST['_wpcf7_posted_data_hash'] );
}
if ( '' === $hash ) {
return false;
}
$tick = $this->posted_data_hash_tick();
// Hash created 0-30 minutes ago.
$expected_1 = $this->create_posted_data_hash( $tick );
if ( hash_equals( $expected_1, $hash ) ) {
return 1;
}
// Hash created 30-60 minutes ago.
$expected_2 = $this->create_posted_data_hash( $tick - 1 );
if ( hash_equals( $expected_2, $hash ) ) {
return 2;
}
return false;
}
/**
* Retrieves the remote IP address of this submission.
*/
private function get_remote_ip_addr() {
$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 = isset( $_SERVER['HTTP_REFERER'] )
? trim( $_SERVER['HTTP_REFERER'] ) : '';
if ( $referer
and 0 === strpos( $referer, $home_url ) ) {
return sanitize_url( $referer );
}
}
$url = preg_replace( '%(?<!:|/)/.*$%', '', $home_url )
. wpcf7_get_request_uri();
return $url;
}
/**
* Runs user input validation.
*
* @return bool True if no invalid field is found.
*/
private function validate() {
if ( $this->invalid_fields ) {
return false;
}
$result = new WPCF7_Validation();
$this->contact_form->validate_schema(
array(
'text' => true,
'file' => false,
'field' => array(),
),
$result
);
$tags = $this->contact_form->scan_form_tags( array(
'feature' => '! file-uploading',
) );
foreach ( $tags as $tag ) {
$type = $tag->type;
$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;
return true;
}
/**
* 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() {
$spam = false;
$skip_spam_check = apply_filters( 'wpcf7_skip_spam_check',
$this->skip_spam_check,
$this
);
if ( $skip_spam_check ) {
return $spam;
}
if ( $this->contact_form->is_true( 'subscribers_only' )
and current_user_can( 'wpcf7_submit', $this->contact_form->id() ) ) {
return $spam;
}
$user_agent = (string) $this->get_meta( 'user_agent' );
if ( strlen( $user_agent ) < 2 ) {
$spam = true;
$this->add_spam_log( array(
'agent' => 'wpcf7',
'reason' => __( "User-Agent string is unnaturally short.", 'contact-form-7' ),
) );
}
if ( ! $this->verify_nonce() ) {
$spam = true;
$this->add_spam_log( array(
'agent' => 'wpcf7',
'reason' => __( "Submitted nonce is invalid.", 'contact-form-7' ),
) );
}
return apply_filters( 'wpcf7_spam', $spam, $this );
}
/**
* Adds a spam log.
*
* @link https://contactform7.com/2019/05/31/why-is-this-message-marked-spam/
*/
public function add_spam_log( $args = '' ) {
$args = wp_parse_args( $args, array(
'agent' => '',
'reason' => '',
) );
$this->spam_log[] = $args;
}
/**
* Retrieves the spam logging data.
*
* @return array Spam logging data.
*/
public function get_spam_log() {
return $this->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() ) {
return true;
}
$nonce = isset( $_POST['_wpnonce'] ) ? $_POST['_wpnonce'] : '';
return wpcf7_verify_nonce( $nonce );
}
/**
* Function called just before sending email.
*/
private function before_send_mail() {
$abort = false;
do_action_ref_array( 'wpcf7_before_send_mail', array(
$this->contact_form,
&$abort,
$this,
) );
return ! $abort;
}
/**
* 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
);
if ( $skip_mail ) {
return true;
}
$result = WPCF7_Mail::send( $contact_form->prop( 'mail' ), 'mail' );
if ( $result ) {
$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 );
}
return true;
}
return false;
}
/**
* 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 ) ) {
return false;
}
$paths = (array) $file_path;
$uploaded_files = array();
$hash_strings = 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 ) {
wpcf7_rmdir_p( $path );
if ( $dir = dirname( $path )
and false !== ( $files = scandir( $dir ) )
and ! array_diff( $files, array( '.', '..' ) ) ) {
// remove parent dir if it's empty.
rmdir( $dir );
}
}
}
}
/**
* 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] ) ) {
continue;
}
$file = $_FILES[$tag->name];
$args = array(
'tag' => $tag,
'name' => $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, $args );
if ( is_wp_error( $new_files ) ) {
$result->invalidate( $tag, $new_files );
} else {
$this->add_uploaded_file( $tag->name, $new_files );
}
$result = apply_filters(
"wpcf7_validate_{$tag->type}",
$result, $tag,
array(
'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,
* or false otherwise.
*/
public function add_extra_attachments( $file_path, $template = 'mail' ) {
if ( ! did_action( 'wpcf7_before_send_mail' ) ) {
return false;
}
$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 ) ) {
return false;
}
if ( ! isset( $this->extra_attachments[$template] ) ) {
$this->extra_attachments[$template] = array();
}
$this->extra_attachments[$template] = array_merge(
$this->extra_attachments[$template],
$extra_attachments
);
return true;
}
/**
* 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];
}
return array();
}
}

View File

@@ -1,6 +0,0 @@
<?php
return array(
'dependencies' => array(),
'version' => WPCF7_VERSION,
);

File diff suppressed because one or more lines are too long

View File

@@ -1,36 +0,0 @@
<?php
class WPCF7_SWV_DateRule extends WPCF7_SWV_Rule {
const rule_name = 'date';
public function matches( $context ) {
if ( false === parent::matches( $context ) ) {
return false;
}
if ( empty( $context['text'] ) ) {
return false;
}
return true;
}
public function validate( $context ) {
$field = $this->get_property( 'field' );
$input = isset( $_POST[$field] ) ? $_POST[$field] : '';
$input = wpcf7_array_flatten( $input );
$input = wpcf7_exclude_blank( $input );
foreach ( $input as $i ) {
if ( ! wpcf7_is_date( $i ) ) {
return new WP_Error( 'wpcf7_invalid_date',
$this->get_property( 'error' )
);
}
}
return true;
}
}

View File

@@ -1,48 +0,0 @@
<?php
class WPCF7_SWV_DayofweekRule extends WPCF7_SWV_Rule {
const rule_name = 'dayofweek';
public function matches( $context ) {
if ( false === parent::matches( $context ) ) {
return false;
}
if ( empty( $context['text'] ) ) {
return false;
}
return true;
}
public function validate( $context ) {
$field = $this->get_property( 'field' );
$input = isset( $_POST[$field] ) ? $_POST[$field] : '';
$input = wpcf7_array_flatten( $input );
$input = wpcf7_exclude_blank( $input );
$acceptable_values = (array) $this->get_property( 'accept' );
$acceptable_values = array_map( 'intval', $acceptable_values );
$acceptable_values = array_filter( $acceptable_values );
$acceptable_values = array_unique( $acceptable_values );
foreach ( $input as $i ) {
if ( wpcf7_is_date( $i ) ) {
$datetime = date_create_immutable( $i, wp_timezone() );
$dow = (int) $datetime->format( 'N' );
if ( ! in_array( $dow, $acceptable_values, true ) ) {
return new WP_Error( 'wpcf7_invalid_dayofweek',
$this->get_property( 'error' )
);
}
}
}
return true;
}
}

View File

@@ -1,36 +0,0 @@
<?php
class WPCF7_SWV_EmailRule extends WPCF7_SWV_Rule {
const rule_name = 'email';
public function matches( $context ) {
if ( false === parent::matches( $context ) ) {
return false;
}
if ( empty( $context['text'] ) ) {
return false;
}
return true;
}
public function validate( $context ) {
$field = $this->get_property( 'field' );
$input = isset( $_POST[$field] ) ? $_POST[$field] : '';
$input = wpcf7_array_flatten( $input );
$input = wpcf7_exclude_blank( $input );
foreach ( $input as $i ) {
if ( ! wpcf7_is_email( $i ) ) {
return new WP_Error( 'wpcf7_invalid_email',
$this->get_property( 'error' )
);
}
}
return true;
}
}

View File

@@ -1,43 +0,0 @@
<?php
class WPCF7_SWV_EnumRule extends WPCF7_SWV_Rule {
const rule_name = 'enum';
public function matches( $context ) {
if ( false === parent::matches( $context ) ) {
return false;
}
if ( empty( $context['text'] ) ) {
return false;
}
return true;
}
public function validate( $context ) {
$field = $this->get_property( 'field' );
$input = isset( $_POST[$field] ) ? $_POST[$field] : '';
$input = wpcf7_array_flatten( $input );
$input = wpcf7_exclude_blank( $input );
$acceptable_values = (array) $this->get_property( 'accept' );
$acceptable_values = array_map( 'strval', $acceptable_values );
$acceptable_values = array_filter( $acceptable_values );
$acceptable_values = array_unique( $acceptable_values );
foreach ( $input as $i ) {
if ( ! in_array( $i, $acceptable_values, true ) ) {
return new WP_Error( 'wpcf7_invalid_enum',
$this->get_property( 'error' )
);
}
}
return true;
}
}

View File

@@ -1,63 +0,0 @@
<?php
class WPCF7_SWV_FileRule extends WPCF7_SWV_Rule {
const rule_name = 'file';
public function matches( $context ) {
if ( false === parent::matches( $context ) ) {
return false;
}
if ( empty( $context['file'] ) ) {
return false;
}
return true;
}
public function validate( $context ) {
$field = $this->get_property( 'field' );
$input = isset( $_FILES[$field]['name'] ) ? $_FILES[$field]['name'] : '';
$input = wpcf7_array_flatten( $input );
$input = wpcf7_exclude_blank( $input );
$acceptable_filetypes = array();
foreach ( (array) $this->get_property( 'accept' ) as $accept ) {
if ( preg_match( '/^\.[a-z0-9]+$/i', $accept ) ) {
$acceptable_filetypes[] = strtolower( $accept );
} else {
foreach ( wpcf7_convert_mime_to_ext( $accept ) as $ext ) {
$acceptable_filetypes[] = sprintf(
'.%s',
strtolower( trim( $ext, ' .' ) )
);
}
}
}
$acceptable_filetypes = array_unique( $acceptable_filetypes );
foreach ( $input as $i ) {
$last_period_pos = strrpos( $i, '.' );
if ( false === $last_period_pos ) { // no period
return new WP_Error( 'wpcf7_invalid_file',
$this->get_property( 'error' )
);
}
$suffix = strtolower( substr( $i, $last_period_pos ) );
if ( ! in_array( $suffix, $acceptable_filetypes, true ) ) {
return new WP_Error( 'wpcf7_invalid_file',
$this->get_property( 'error' )
);
}
}
return true;
}
}

View File

@@ -1,42 +0,0 @@
<?php
class WPCF7_SWV_MaxDateRule extends WPCF7_SWV_Rule {
const rule_name = 'maxdate';
public function matches( $context ) {
if ( false === parent::matches( $context ) ) {
return false;
}
if ( empty( $context['text'] ) ) {
return false;
}
return true;
}
public function validate( $context ) {
$field = $this->get_property( 'field' );
$input = isset( $_POST[$field] ) ? $_POST[$field] : '';
$input = wpcf7_array_flatten( $input );
$input = wpcf7_exclude_blank( $input );
$threshold = $this->get_property( 'threshold' );
if ( ! wpcf7_is_date( $threshold ) ) {
return true;
}
foreach ( $input as $i ) {
if ( wpcf7_is_date( $i ) and $threshold < $i ) {
return new WP_Error( 'wpcf7_invalid_maxdate',
$this->get_property( 'error' )
);
}
}
return true;
}
}

View File

@@ -1,40 +0,0 @@
<?php
class WPCF7_SWV_MaxFileSizeRule extends WPCF7_SWV_Rule {
const rule_name = 'maxfilesize';
public function matches( $context ) {
if ( false === parent::matches( $context ) ) {
return false;
}
if ( empty( $context['file'] ) ) {
return false;
}
return true;
}
public function validate( $context ) {
$field = $this->get_property( 'field' );
$input = isset( $_FILES[$field]['size'] ) ? $_FILES[$field]['size'] : '';
$input = wpcf7_array_flatten( $input );
$input = wpcf7_exclude_blank( $input );
if ( empty( $input ) ) {
return true;
}
$threshold = $this->get_property( 'threshold' );
if ( $threshold < array_sum( $input ) ) {
return new WP_Error( 'wpcf7_invalid_maxfilesize',
$this->get_property( 'error' )
);
}
return true;
}
}

View File

@@ -1,40 +0,0 @@
<?php
class WPCF7_SWV_MaxItemsRule extends WPCF7_SWV_Rule {
const rule_name = 'maxitems';
public function matches( $context ) {
if ( false === parent::matches( $context ) ) {
return false;
}
if ( empty( $context['text'] ) ) {
return false;
}
return true;
}
public function validate( $context ) {
$field = $this->get_property( 'field' );
$input = isset( $_POST[$field] ) ? $_POST[$field] : '';
$input = wpcf7_array_flatten( $input );
$input = wpcf7_exclude_blank( $input );
$threshold = $this->get_property( 'threshold' );
if ( ! wpcf7_is_number( $threshold ) ) {
return true;
}
if ( (int) $threshold < count( $input ) ) {
return new WP_Error( 'wpcf7_invalid_maxitems',
$this->get_property( 'error' )
);
}
return true;
}
}

View File

@@ -1,46 +0,0 @@
<?php
class WPCF7_SWV_MaxLengthRule extends WPCF7_SWV_Rule {
const rule_name = 'maxlength';
public function matches( $context ) {
if ( false === parent::matches( $context ) ) {
return false;
}
if ( empty( $context['text'] ) ) {
return false;
}
return true;
}
public function validate( $context ) {
$field = $this->get_property( 'field' );
$input = isset( $_POST[$field] ) ? $_POST[$field] : '';
$input = wpcf7_array_flatten( $input );
$input = wpcf7_exclude_blank( $input );
if ( empty( $input ) ) {
return true;
}
$total = 0;
foreach ( $input as $i ) {
$total += wpcf7_count_code_units( $i );
}
$threshold = (int) $this->get_property( 'threshold' );
if ( $total <= $threshold ) {
return true;
} else {
return new WP_Error( 'wpcf7_invalid_maxlength',
$this->get_property( 'error' )
);
}
}
}

View File

@@ -1,42 +0,0 @@
<?php
class WPCF7_SWV_MaxNumberRule extends WPCF7_SWV_Rule {
const rule_name = 'maxnumber';
public function matches( $context ) {
if ( false === parent::matches( $context ) ) {
return false;
}
if ( empty( $context['text'] ) ) {
return false;
}
return true;
}
public function validate( $context ) {
$field = $this->get_property( 'field' );
$input = isset( $_POST[$field] ) ? $_POST[$field] : '';
$input = wpcf7_array_flatten( $input );
$input = wpcf7_exclude_blank( $input );
$threshold = $this->get_property( 'threshold' );
if ( ! wpcf7_is_number( $threshold ) ) {
return true;
}
foreach ( $input as $i ) {
if ( wpcf7_is_number( $i ) and (float) $threshold < (float) $i ) {
return new WP_Error( 'wpcf7_invalid_maxnumber',
$this->get_property( 'error' )
);
}
}
return true;
}
}

View File

@@ -1,42 +0,0 @@
<?php
class WPCF7_SWV_MinDateRule extends WPCF7_SWV_Rule {
const rule_name = 'mindate';
public function matches( $context ) {
if ( false === parent::matches( $context ) ) {
return false;
}
if ( empty( $context['text'] ) ) {
return false;
}
return true;
}
public function validate( $context ) {
$field = $this->get_property( 'field' );
$input = isset( $_POST[$field] ) ? $_POST[$field] : '';
$input = wpcf7_array_flatten( $input );
$input = wpcf7_exclude_blank( $input );
$threshold = $this->get_property( 'threshold' );
if ( ! wpcf7_is_date( $threshold ) ) {
return true;
}
foreach ( $input as $i ) {
if ( wpcf7_is_date( $i ) and $i < $threshold ) {
return new WP_Error( 'wpcf7_invalid_mindate',
$this->get_property( 'error' )
);
}
}
return true;
}
}

View File

@@ -1,40 +0,0 @@
<?php
class WPCF7_SWV_MinFileSizeRule extends WPCF7_SWV_Rule {
const rule_name = 'minfilesize';
public function matches( $context ) {
if ( false === parent::matches( $context ) ) {
return false;
}
if ( empty( $context['file'] ) ) {
return false;
}
return true;
}
public function validate( $context ) {
$field = $this->get_property( 'field' );
$input = isset( $_FILES[$field]['size'] ) ? $_FILES[$field]['size'] : '';
$input = wpcf7_array_flatten( $input );
$input = wpcf7_exclude_blank( $input );
if ( empty( $input ) ) {
return true;
}
$threshold = $this->get_property( 'threshold' );
if ( array_sum( $input ) < $threshold ) {
return new WP_Error( 'wpcf7_invalid_minfilesize',
$this->get_property( 'error' )
);
}
return true;
}
}

View File

@@ -1,40 +0,0 @@
<?php
class WPCF7_SWV_MinItemsRule extends WPCF7_SWV_Rule {
const rule_name = 'minitems';
public function matches( $context ) {
if ( false === parent::matches( $context ) ) {
return false;
}
if ( empty( $context['text'] ) ) {
return false;
}
return true;
}
public function validate( $context ) {
$field = $this->get_property( 'field' );
$input = isset( $_POST[$field] ) ? $_POST[$field] : '';
$input = wpcf7_array_flatten( $input );
$input = wpcf7_exclude_blank( $input );
$threshold = $this->get_property( 'threshold' );
if ( ! wpcf7_is_number( $threshold ) ) {
return true;
}
if ( count( $input ) < (int) $threshold ) {
return new WP_Error( 'wpcf7_invalid_minitems',
$this->get_property( 'error' )
);
}
return true;
}
}

View File

@@ -1,46 +0,0 @@
<?php
class WPCF7_SWV_MinLengthRule extends WPCF7_SWV_Rule {
const rule_name = 'minlength';
public function matches( $context ) {
if ( false === parent::matches( $context ) ) {
return false;
}
if ( empty( $context['text'] ) ) {
return false;
}
return true;
}
public function validate( $context ) {
$field = $this->get_property( 'field' );
$input = isset( $_POST[$field] ) ? $_POST[$field] : '';
$input = wpcf7_array_flatten( $input );
$input = wpcf7_exclude_blank( $input );
if ( empty( $input ) ) {
return true;
}
$total = 0;
foreach ( $input as $i ) {
$total += wpcf7_count_code_units( $i );
}
$threshold = (int) $this->get_property( 'threshold' );
if ( $threshold <= $total ) {
return true;
} else {
return new WP_Error( 'wpcf7_invalid_minlength',
$this->get_property( 'error' )
);
}
}
}

View File

@@ -1,42 +0,0 @@
<?php
class WPCF7_SWV_MinNumberRule extends WPCF7_SWV_Rule {
const rule_name = 'minnumber';
public function matches( $context ) {
if ( false === parent::matches( $context ) ) {
return false;
}
if ( empty( $context['text'] ) ) {
return false;
}
return true;
}
public function validate( $context ) {
$field = $this->get_property( 'field' );
$input = isset( $_POST[$field] ) ? $_POST[$field] : '';
$input = wpcf7_array_flatten( $input );
$input = wpcf7_exclude_blank( $input );
$threshold = $this->get_property( 'threshold' );
if ( ! wpcf7_is_number( $threshold ) ) {
return true;
}
foreach ( $input as $i ) {
if ( wpcf7_is_number( $i ) and (float) $i < (float) $threshold ) {
return new WP_Error( 'wpcf7_invalid_minnumber',
$this->get_property( 'error' )
);
}
}
return true;
}
}

View File

@@ -1,36 +0,0 @@
<?php
class WPCF7_SWV_NumberRule extends WPCF7_SWV_Rule {
const rule_name = 'number';
public function matches( $context ) {
if ( false === parent::matches( $context ) ) {
return false;
}
if ( empty( $context['text'] ) ) {
return false;
}
return true;
}
public function validate( $context ) {
$field = $this->get_property( 'field' );
$input = isset( $_POST[$field] ) ? $_POST[$field] : '';
$input = wpcf7_array_flatten( $input );
$input = wpcf7_exclude_blank( $input );
foreach ( $input as $i ) {
if ( ! wpcf7_is_number( $i ) ) {
return new WP_Error( 'wpcf7_invalid_number',
$this->get_property( 'error' )
);
}
}
return true;
}
}

View File

@@ -1,36 +0,0 @@
<?php
class WPCF7_SWV_RequiredRule extends WPCF7_SWV_Rule {
const rule_name = 'required';
public function matches( $context ) {
if ( false === parent::matches( $context ) ) {
return false;
}
if ( empty( $context['text'] ) ) {
return false;
}
return true;
}
public function validate( $context ) {
$field = $this->get_property( 'field' );
$input = isset( $_POST[$field] ) ? $_POST[$field] : '';
$input = wpcf7_array_flatten( $input );
$input = wpcf7_exclude_blank( $input );
if ( empty( $input ) ) {
return new WP_Error( 'wpcf7_invalid_required',
$this->get_property( 'error' )
);
}
return true;
}
}

View File

@@ -1,37 +0,0 @@
<?php
class WPCF7_SWV_RequiredFileRule extends WPCF7_SWV_Rule {
const rule_name = 'requiredfile';
public function matches( $context ) {
if ( false === parent::matches( $context ) ) {
return false;
}
if ( empty( $context['file'] ) ) {
return false;
}
return true;
}
public function validate( $context ) {
$field = $this->get_property( 'field' );
$input = isset( $_FILES[$field]['tmp_name'] )
? $_FILES[$field]['tmp_name'] : '';
$input = wpcf7_array_flatten( $input );
$input = wpcf7_exclude_blank( $input );
if ( empty( $input ) ) {
return new WP_Error( 'wpcf7_invalid_requiredfile',
$this->get_property( 'error' )
);
}
return true;
}
}

View File

@@ -1,36 +0,0 @@
<?php
class WPCF7_SWV_TelRule extends WPCF7_SWV_Rule {
const rule_name = 'tel';
public function matches( $context ) {
if ( false === parent::matches( $context ) ) {
return false;
}
if ( empty( $context['text'] ) ) {
return false;
}
return true;
}
public function validate( $context ) {
$field = $this->get_property( 'field' );
$input = isset( $_POST[$field] ) ? $_POST[$field] : '';
$input = wpcf7_array_flatten( $input );
$input = wpcf7_exclude_blank( $input );
foreach ( $input as $i ) {
if ( ! wpcf7_is_tel( $i ) ) {
return new WP_Error( 'wpcf7_invalid_tel',
$this->get_property( 'error' )
);
}
}
return true;
}
}

View File

@@ -1,36 +0,0 @@
<?php
class WPCF7_SWV_TimeRule extends WPCF7_SWV_Rule {
const rule_name = 'time';
public function matches( $context ) {
if ( false === parent::matches( $context ) ) {
return false;
}
if ( empty( $context['text'] ) ) {
return false;
}
return true;
}
public function validate( $context ) {
$field = $this->get_property( 'field' );
$input = isset( $_POST[$field] ) ? $_POST[$field] : '';
$input = wpcf7_array_flatten( $input );
$input = wpcf7_exclude_blank( $input );
foreach ( $input as $i ) {
if ( ! wpcf7_is_time( $i ) ) {
return new WP_Error( 'wpcf7_invalid_time',
$this->get_property( 'error' )
);
}
}
return true;
}
}

View File

@@ -1,36 +0,0 @@
<?php
class WPCF7_SWV_URLRule extends WPCF7_SWV_Rule {
const rule_name = 'url';
public function matches( $context ) {
if ( false === parent::matches( $context ) ) {
return false;
}
if ( empty( $context['text'] ) ) {
return false;
}
return true;
}
public function validate( $context ) {
$field = $this->get_property( 'field' );
$input = isset( $_POST[$field] ) ? $_POST[$field] : '';
$input = wpcf7_array_flatten( $input );
$input = wpcf7_exclude_blank( $input );
foreach ( $input as $i ) {
if ( ! wpcf7_is_url( $i ) ) {
return new WP_Error( 'wpcf7_invalid_url',
$this->get_property( 'error' )
);
}
}
return true;
}
}

View File

@@ -1,57 +0,0 @@
<?php
trait WPCF7_SWV_SchemaHolder {
protected $schema;
/**
* Retrieves SWV schema for this holder object (contact form).
*
* @return WPCF7_SWV_Schema The schema object.
*/
public function get_schema() {
if ( isset( $this->schema ) ) {
return $this->schema;
}
$schema = new WPCF7_SWV_Schema( array(
'locale' => isset( $this->locale ) ? $this->locale : '',
) );
do_action( 'wpcf7_swv_create_schema', $schema, $this );
return $this->schema = $schema;
}
/**
* Validates form inputs based on the schema and given context.
*/
public function validate_schema( $context, WPCF7_Validation $validity ) {
$callback = static function ( $rule ) use ( &$callback, $context, $validity ) {
if ( ! $rule->matches( $context ) ) {
return;
}
if ( $rule instanceof WPCF7_SWV_CompositeRule ) {
foreach ( $rule->rules() as $child_rule ) {
call_user_func( $callback, $child_rule );
}
} else {
$field = $rule->get_property( 'field' );
if ( $validity->is_valid( $field ) ) {
$result = $rule->validate( $context );
if ( is_wp_error( $result ) ) {
$validity->invalidate( $field, $result );
}
}
}
};
call_user_func( $callback, $this->get_schema() );
}
}

View File

@@ -1,26 +0,0 @@
<?php
add_action(
'wp_enqueue_scripts',
static function () {
$assets = array();
$asset_file = wpcf7_plugin_path( 'includes/swv/js/index.asset.php' );
if ( file_exists( $asset_file ) ) {
$assets = include( $asset_file );
}
$assets = wp_parse_args( $assets, array(
'dependencies' => array(),
'version' => WPCF7_VERSION,
) );
wp_register_script( 'swv',
wpcf7_plugin_url( 'includes/swv/js/index.js' ),
$assets['dependencies'],
$assets['version'],
true
);
},
10, 0
);

View File

@@ -1,295 +0,0 @@
<?php
/**
* Schema-Woven Validation API
*/
require_once WPCF7_PLUGIN_DIR . '/includes/swv/schema-holder.php';
require_once WPCF7_PLUGIN_DIR . '/includes/swv/script-loader.php';
/**
* Returns an associative array of SWV rules.
*/
function wpcf7_swv_available_rules() {
$rules = array(
'required' => 'WPCF7_SWV_RequiredRule',
'requiredfile' => 'WPCF7_SWV_RequiredFileRule',
'email' => 'WPCF7_SWV_EmailRule',
'url' => 'WPCF7_SWV_URLRule',
'tel' => 'WPCF7_SWV_TelRule',
'number' => 'WPCF7_SWV_NumberRule',
'date' => 'WPCF7_SWV_DateRule',
'time' => 'WPCF7_SWV_TimeRule',
'file' => 'WPCF7_SWV_FileRule',
'enum' => 'WPCF7_SWV_EnumRule',
'dayofweek' => 'WPCF7_SWV_DayofweekRule',
'minitems' => 'WPCF7_SWV_MinItemsRule',
'maxitems' => 'WPCF7_SWV_MaxItemsRule',
'minlength' => 'WPCF7_SWV_MinLengthRule',
'maxlength' => 'WPCF7_SWV_MaxLengthRule',
'minnumber' => 'WPCF7_SWV_MinNumberRule',
'maxnumber' => 'WPCF7_SWV_MaxNumberRule',
'mindate' => 'WPCF7_SWV_MinDateRule',
'maxdate' => 'WPCF7_SWV_MaxDateRule',
'minfilesize' => 'WPCF7_SWV_MinFileSizeRule',
'maxfilesize' => 'WPCF7_SWV_MaxFileSizeRule',
);
return apply_filters( 'wpcf7_swv_available_rules', $rules );
}
add_action( 'wpcf7_init', 'wpcf7_swv_load_rules', 10, 0 );
/**
* Loads SWV fules.
*/
function wpcf7_swv_load_rules() {
$rules = wpcf7_swv_available_rules();
foreach ( array_keys( $rules ) as $rule ) {
$file = sprintf( '%s.php', $rule );
$path = path_join( WPCF7_PLUGIN_DIR . '/includes/swv/rules', $file );
if ( file_exists( $path ) ) {
include_once $path;
}
}
}
/**
* Creates an SWV rule object.
*
* @param string $rule_name Rule name.
* @param string|array $properties Optional. Rule properties.
* @return WPCF7_SWV_Rule|null The rule object, or null if it failed.
*/
function wpcf7_swv_create_rule( $rule_name, $properties = '' ) {
$rules = wpcf7_swv_available_rules();
if ( isset( $rules[$rule_name] ) ) {
return new $rules[$rule_name]( $properties );
}
}
/**
* Returns an associative array of JSON Schema for Contact Form 7 SWV.
*/
function wpcf7_swv_get_meta_schema() {
return array(
'$schema' => 'https://json-schema.org/draft/2020-12/schema',
'title' => 'Contact Form 7 SWV',
'description' => 'Contact Form 7 SWV meta-schema',
'type' => 'object',
'properties' => array(
'version' => array(
'type' => 'string',
),
'locale' => array(
'type' => 'string',
),
'rules' => array(
'type' => 'array',
'items' => array(
'type' => 'object',
'properties' => array(
'rule' => array(
'type' => 'string',
'enum' => array_keys( wpcf7_swv_available_rules() ),
),
'field' => array(
'type' => 'string',
'pattern' => '^[A-Za-z][-A-Za-z0-9_:]*$',
),
'error' => array(
'type' => 'string',
),
'accept' => array(
'type' => 'array',
'items' => array(
'type' => 'string',
),
),
'threshold' => array(
'type' => 'string',
),
),
'required' => array( 'rule' ),
),
),
),
);
}
/**
* The base class of SWV rules.
*/
abstract class WPCF7_SWV_Rule {
protected $properties = array();
public function __construct( $properties = '' ) {
$this->properties = wp_parse_args( $properties, array() );
}
/**
* Returns true if this rule matches the given context.
*
* @param array $context Context.
*/
public function matches( $context ) {
$field = $this->get_property( 'field' );
if ( ! empty( $context['field'] ) ) {
if ( $field and ! in_array( $field, (array) $context['field'], true ) ) {
return false;
}
}
return true;
}
/**
* Validates with this rule's logic.
*
* @param array $context Context.
*/
public function validate( $context ) {
return true;
}
/**
* Converts the properties to an array.
*
* @return array Array of properties.
*/
public function to_array() {
$properties = (array) $this->properties;
if ( defined( 'static::rule_name' ) and static::rule_name ) {
$properties = array( 'rule' => static::rule_name ) + $properties;
}
return $properties;
}
/**
* Returns the property value specified by the given property name.
*
* @param string $name Property name.
* @return mixed Property value.
*/
public function get_property( $name ) {
if ( isset( $this->properties[$name] ) ) {
return $this->properties[$name];
}
}
}
/**
* The base class of SWV composite rules.
*/
abstract class WPCF7_SWV_CompositeRule extends WPCF7_SWV_Rule {
protected $rules = array();
/**
* Adds a sub-rule to this composite rule.
*
* @param WPCF7_SWV_Rule $rule Sub-rule to be added.
*/
public function add_rule( $rule ) {
if ( $rule instanceof WPCF7_SWV_Rule ) {
$this->rules[] = $rule;
}
}
/**
* Returns an iterator of sub-rules.
*/
public function rules() {
foreach ( $this->rules as $rule ) {
yield $rule;
}
}
/**
* Returns true if this rule matches the given context.
*
* @param array $context Context.
*/
public function matches( $context ) {
return true;
}
/**
* Validates with this rule's logic.
*
* @param array $context Context.
*/
public function validate( $context ) {
foreach ( $this->rules() as $rule ) {
if ( $rule->matches( $context ) ) {
$result = $rule->validate( $context );
if ( is_wp_error( $result ) ) {
return $result;
}
}
}
return true;
}
/**
* Converts the properties to an array.
*
* @return array Array of properties.
*/
public function to_array() {
$rules_arrays = array_map(
static function ( $rule ) {
return $rule->to_array();
},
$this->rules
);
return array_merge(
parent::to_array(),
array(
'rules' => $rules_arrays,
)
);
}
}
/**
* The schema class as a composite rule.
*/
class WPCF7_SWV_Schema extends WPCF7_SWV_CompositeRule {
const version = 'Contact Form 7 SWV Schema 2023-07';
public function __construct( $properties = '' ) {
$this->properties = wp_parse_args( $properties, array(
'version' => self::version,
) );
}
}

View File

@@ -1,133 +0,0 @@
<?php
add_action( 'wpcf7_upgrade', 'wpcf7_upgrade_58', 10, 2 );
/**
* Runs functions necessary when upgrading from old plugin versions before 5.8.
*
* @since 5.8.0 New `_config_validation` post meta is introduced.
*/
function wpcf7_upgrade_58( $new_ver, $old_ver ) {
if ( ! version_compare( $old_ver, '5.8-dev', '<' ) ) {
return;
}
$posts = WPCF7_ContactForm::find( array(
'post_status' => 'any',
'posts_per_page' => -1,
) );
foreach ( $posts as $post ) {
$post_id = $post->id();
// Delete the old post meta for config-validation results.
delete_post_meta( $post_id, '_config_errors' );
// Add the contact form hash.
add_post_meta( $post_id, '_hash',
wpcf7_generate_contact_form_hash( $post_id ),
true // Unique
);
}
}
add_action( 'wpcf7_upgrade', 'wpcf7_convert_to_cpt', 10, 2 );
/**
* Converts old data in the dedicated database table to custom posts.
*
* @since 3.0.0 `wpcf7_contact_form` CPT is introduced.
*/
function wpcf7_convert_to_cpt( $new_ver, $old_ver ) {
global $wpdb;
if ( ! version_compare( $old_ver, '3.0-dev', '<' ) ) {
return;
}
$old_rows = array();
$table_name = $wpdb->prefix . "contact_form_7";
if ( $wpdb->get_var( "SHOW TABLES LIKE '$table_name'" ) ) {
$old_rows = $wpdb->get_results( "SELECT * FROM $table_name" );
} elseif ( $opt = get_option( 'wpcf7' )
and ! empty( $opt['contact_forms'] ) ) {
foreach ( (array) $opt['contact_forms'] as $key => $value ) {
$old_rows[] = (object) array_merge(
$value,
array( 'cf7_unit_id' => $key )
);
}
}
foreach ( (array) $old_rows as $row ) {
$q = "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_old_cf7_unit_id'"
. $wpdb->prepare( " AND meta_value = %d", $row->cf7_unit_id );
if ( $wpdb->get_var( $q ) ) {
continue;
}
$postarr = array(
'post_type' => 'wpcf7_contact_form',
'post_status' => 'publish',
'post_title' => maybe_unserialize( $row->title ),
);
$post_id = wp_insert_post( $postarr );
if ( $post_id ) {
update_post_meta( $post_id, '_old_cf7_unit_id', $row->cf7_unit_id );
$metas = array(
'form',
'mail',
'mail_2',
'messages',
'additional_settings',
);
foreach ( $metas as $meta ) {
update_post_meta( $post_id, '_' . $meta,
wpcf7_normalize_newline_deep( maybe_unserialize( $row->{$meta} ) )
);
}
}
}
}
add_action( 'wpcf7_upgrade', 'wpcf7_prepend_underscore', 10, 2 );
/**
* Prepends an underscore to post meta keys.
*/
function wpcf7_prepend_underscore( $new_ver, $old_ver ) {
if ( version_compare( $old_ver, '3.0-dev', '<' ) ) {
return;
}
if ( ! version_compare( $old_ver, '3.3-dev', '<' ) ) {
return;
}
$posts = WPCF7_ContactForm::find( array(
'post_status' => 'any',
'posts_per_page' => -1,
) );
foreach ( $posts as $post ) {
$props = $post->get_properties();
foreach ( $props as $prop => $value ) {
if ( metadata_exists( 'post', $post->id(), '_' . $prop ) ) {
continue;
}
update_post_meta( $post->id(), '_' . $prop, $value );
delete_post_meta( $post->id(), $prop );
}
}
}

View File

@@ -1,300 +0,0 @@
<?php
/**
* Checks whether a string is a valid NAME token.
*
* ID and NAME tokens must begin with a letter ([A-Za-z])
* and may be followed by any number of letters, digits ([0-9]),
* hyphens ("-"), underscores ("_"), colons (":"), and periods (".").
*
* @link http://www.w3.org/TR/html401/types.html#h-6.2
*
* @return bool True if it is a valid name, false if not.
*/
function wpcf7_is_name( $text ) {
return preg_match( '/^[A-Za-z][-A-Za-z0-9_:.]*$/', $text );
}
/**
* Checks whether the given text is a well-formed email address.
*/
function wpcf7_is_email( $text ) {
$result = is_email( $text );
return apply_filters( 'wpcf7_is_email', $result, $text );
}
/**
* Checks whether the given text is a well-formed URL.
*/
function wpcf7_is_url( $text ) {
$scheme = wp_parse_url( $text, PHP_URL_SCHEME );
$result = $scheme && in_array( $scheme, wp_allowed_protocols(), true );
return apply_filters( 'wpcf7_is_url', $result, $text );
}
/**
* Checks whether the given text is a well-formed telephone number.
*/
function wpcf7_is_tel( $text ) {
$text = preg_replace( '%[()/.*#\s-]+%', '', $text );
$result = preg_match( '/^[+]?[0-9]+$/', $text );
return apply_filters( 'wpcf7_is_tel', $result, $text );
}
/**
* Checks whether the given text is a well-formed number.
*
* @link https://html.spec.whatwg.org/multipage/input.html#number-state-(type=number)
*/
function wpcf7_is_number( $text ) {
$result = false;
$patterns = array(
'/^[-]?[0-9]+(?:[eE][+-]?[0-9]+)?$/',
'/^[-]?(?:[0-9]+)?[.][0-9]+(?:[eE][+-]?[0-9]+)?$/',
);
foreach ( $patterns as $pattern ) {
if ( preg_match( $pattern, $text ) ) {
$result = true;
break;
}
}
return apply_filters( 'wpcf7_is_number', $result, $text );
}
/**
* Checks whether the given text is a valid date.
*
* @link https://html.spec.whatwg.org/multipage/input.html#date-state-(type=date)
*/
function wpcf7_is_date( $text ) {
$result = preg_match(
'/^([0-9]{4,})-([0-9]{2})-([0-9]{2})$/',
$text,
$matches
);
if ( $result ) {
$result = checkdate( $matches[2], $matches[3], $matches[1] );
}
return apply_filters( 'wpcf7_is_date', $result, $text );
}
/**
* Checks whether the given text is a valid time.
*
* @link https://html.spec.whatwg.org/multipage/input.html#time-state-(type=time)
*/
function wpcf7_is_time( $text ) {
$result = preg_match(
'/^([0-9]{2})\:([0-9]{2})(?:\:([0-9]{2}))?$/',
$text,
$matches
);
if ( $result ) {
$hour = (int) $matches[1];
$minute = (int) $matches[2];
$second = empty( $matches[3] ) ? 0 : (int) $matches[3];
$result = 0 <= $hour && $hour <= 23 &&
0 <= $minute && $minute <= 59 &&
0 <= $second && $second <= 59;
}
return apply_filters( 'wpcf7_is_time', $result, $text );
}
/**
* Checks whether the given text is a well-formed mailbox list.
*
* @param string|array $mailbox_list The subject to be checked.
* Comma-separated string or an array of mailboxes.
* @return array|bool Array of email addresses if all items are well-formed
* mailbox, false if not.
*/
function wpcf7_is_mailbox_list( $mailbox_list ) {
if ( ! is_array( $mailbox_list ) ) {
$mailbox_text = (string) $mailbox_list;
$mailbox_text = preg_replace(
'/\\\\(?:\"|\')/',
'esc-quote',
$mailbox_text
);
$mailbox_text = preg_replace(
'/(?:\".*?\"|\'.*?\')/',
'quoted-string',
$mailbox_text
);
$mailbox_list = explode( ',', $mailbox_text );
}
$addresses = array();
foreach ( $mailbox_list as $mailbox ) {
if ( ! is_string( $mailbox ) ) {
return false;
}
$mailbox = trim( $mailbox );
if ( '' === $mailbox ) {
continue;
}
if ( preg_match( '/<(.+)>$/', $mailbox, $matches ) ) {
$addr_spec = $matches[1];
} else {
$addr_spec = $mailbox;
}
if ( ! wpcf7_is_email( $addr_spec ) ) {
return false;
}
$addresses[] = $addr_spec;
}
return $addresses;
}
/**
* Checks whether an email address belongs to a domain.
*
* @param string $email A mailbox or a comma-separated list of mailboxes.
* @param string $domain Internet domain name.
* @return bool True if all of the email addresses belong to the domain,
* false if not.
*/
function wpcf7_is_email_in_domain( $email, $domain ) {
$email_list = wpcf7_is_mailbox_list( $email );
if ( false === $email_list ) {
return false;
}
$domain = strtolower( $domain );
foreach ( $email_list as $email ) {
$email_domain = substr( $email, strrpos( $email, '@' ) + 1 );
$email_domain = strtolower( $email_domain );
$domain_parts = explode( '.', $domain );
do {
$site_domain = implode( '.', $domain_parts );
if ( $site_domain == $email_domain ) {
continue 2;
}
array_shift( $domain_parts );
} while ( $domain_parts );
return false;
}
return true;
}
/**
* Checks whether an email address belongs to the site domain.
*/
function wpcf7_is_email_in_site_domain( $email ) {
if ( wpcf7_is_localhost() ) {
return true;
}
$homes = array(
home_url(),
network_home_url(),
);
$homes = array_unique( $homes );
foreach ( $homes as $home ) {
$sitename = wp_parse_url( $home, PHP_URL_HOST );
if ( WP_Http::is_ip_address( $sitename ) ) {
return true;
}
if ( wpcf7_is_email_in_domain( $email, $sitename ) ) {
return true;
}
}
return false;
}
/**
* Verifies that a given file path is under the directories that WordPress
* manages for user contents.
*
* Returns false if the file at the given path does not exist yet.
*
* @param string $path A file path.
* @return bool True if the path is under the content directories,
* false otherwise.
*/
function wpcf7_is_file_path_in_content_dir( $path ) {
if ( ! is_string( $path ) or '' === $path ) {
return false;
}
$callback = static function ( $path, $dir ) {
if ( $real_path = realpath( $path ) ) {
$path = $real_path;
} else {
return false;
}
if ( $real_dir = realpath( $dir ) ) {
$dir = trailingslashit( $real_dir );
} else {
return false;
}
return str_starts_with(
wp_normalize_path( $path ),
wp_normalize_path( $dir )
);
};
if (
call_user_func( $callback, $path, WP_CONTENT_DIR )
) {
return true;
}
if (
defined( 'UPLOADS' ) and
call_user_func( $callback, $path, ABSPATH . UPLOADS )
) {
return true;
}
if (
defined( 'WP_TEMP_DIR' ) and
call_user_func( $callback, $path, WP_TEMP_DIR )
) {
return true;
}
return false;
}

View File

@@ -1,146 +0,0 @@
<?php
/**
* Server-side user input validation manager.
*/
class WPCF7_Validation implements ArrayAccess {
private $invalid_fields = array();
private $container = array();
public function __construct() {
$this->container = array(
'valid' => true,
'reason' => array(),
'idref' => array(),
);
}
/**
* Marks a form control as an invalid field.
*
* @param WPCF7_FormTag|array|string $context Context representing the
* target field.
* @param WP_Error|string $error The error of the field.
*/
public function invalidate( $context, $error ) {
if ( $context instanceof WPCF7_FormTag ) {
$tag = $context;
} elseif ( is_array( $context ) ) {
$tag = new WPCF7_FormTag( $context );
} elseif ( is_string( $context ) ) {
$tags = wpcf7_scan_form_tags( array( 'name' => trim( $context ) ) );
$tag = $tags ? new WPCF7_FormTag( $tags[0] ) : null;
}
$name = ! empty( $tag ) ? $tag->name : null;
if ( empty( $name )
or ! wpcf7_is_name( $name ) ) {
return;
}
if ( is_wp_error( $error ) ) {
$message = $error->get_error_message();
} else {
$message = $error;
}
if ( $this->is_valid( $name ) ) {
$id = $tag->get_id_option();
if ( empty( $id )
or ! wpcf7_is_name( $id ) ) {
$id = null;
}
$this->invalid_fields[$name] = array(
'reason' => (string) $message,
'idref' => $id,
);
}
}
/**
* Returns true if the target field is valid.
*
* @param string|null $name Optional. If specified, this is the name of
* the target field. Default null.
* @return bool True if the target field has no error. If no target is
* specified, returns true if all fields are valid.
* Otherwise false.
*/
public function is_valid( $name = null ) {
if ( ! empty( $name ) ) {
return ! isset( $this->invalid_fields[$name] );
} else {
return empty( $this->invalid_fields );
}
}
/**
* Retrieves an associative array of invalid fields.
*
* @return array The associative array of invalid fields.
*/
public function get_invalid_fields() {
return $this->invalid_fields;
}
/**
* Assigns a value to the specified offset.
*
* @link https://www.php.net/manual/en/arrayaccess.offsetset.php
*/
#[ReturnTypeWillChange]
public function offsetSet( $offset, $value ) {
if ( isset( $this->container[$offset] ) ) {
$this->container[$offset] = $value;
}
if ( 'reason' == $offset
and is_array( $value ) ) {
foreach ( $value as $k => $v ) {
$this->invalidate( $k, $v );
}
}
}
/**
* Returns the value at specified offset.
*
* @link https://www.php.net/manual/en/arrayaccess.offsetget.php
*/
#[ReturnTypeWillChange]
public function offsetGet( $offset ) {
if ( isset( $this->container[$offset] ) ) {
return $this->container[$offset];
}
}
/**
* Returns true if the specified offset exists.
*
* @link https://www.php.net/manual/en/arrayaccess.offsetexists.php
*/
#[ReturnTypeWillChange]
public function offsetExists( $offset ) {
return isset( $this->container[$offset] );
}
/**
* Unsets an offset.
*
* @link https://www.php.net/manual/en/arrayaccess.offsetunset.php
*/
#[ReturnTypeWillChange]
public function offsetUnset( $offset ) {
}
}