includes/mail-tag.php 0000644 00000010142 14720664361 0010565 0 ustar 00 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;
}
}
use Contactable\SWV;
/**
* Mail-tag output calculator.
*/
class WPCF7_MailTag_OutputCalculator {
const email = 0b100;
const text = 0b010;
const blank = 0b001;
private $contact_form;
public function __construct( WPCF7_ContactForm $contact_form ) {
$this->contact_form = $contact_form;
}
public function calc_output( WPCF7_MailTag $mail_tag ) {
return $this->calc_swv_result(
$mail_tag,
$this->contact_form->get_schema()
);
}
private function calc_swv_result( WPCF7_MailTag $mail_tag, SWV\Rule $rule ) {
if ( $rule instanceof SWV\AnyRule ) {
$result = 0b000;
foreach ( $rule->rules() as $child_rule ) {
$result |= $this->calc_swv_result( $mail_tag, $child_rule );
}
return $result;
}
if ( $rule instanceof SWV\CompositeRule ) {
$result = 0b111;
foreach ( $rule->rules() as $child_rule ) {
$result &= $this->calc_swv_result( $mail_tag, $child_rule );
}
return $result;
}
$field_prop = $rule->get_property( 'field' );
if ( empty( $field_prop ) or $field_prop !== $mail_tag->field_name() ) {
return self::email | self::text | self::blank;
}
if ( $rule instanceof SWV\RequiredRule ) {
return ~ self::blank;
}
if ( $rule instanceof SWV\EmailRule ) {
return self::email | self::blank;
}
if ( $rule instanceof SWV\EnumRule ) {
$acceptable_values = (array) $rule->get_property( 'accept' );
$acceptable_values = array_map( 'strval', $acceptable_values );
$acceptable_values = array_filter( $acceptable_values );
$acceptable_values = array_unique( $acceptable_values );
if ( ! $mail_tag->get_option( 'do_not_heat' ) ) {
$pipes = $this->contact_form->get_pipes(
$mail_tag->field_name()
);
$acceptable_values = array_map(
static function ( $val ) use ( $pipes ) {
return $pipes->do_pipe( $val );
},
$acceptable_values
);
}
$email_values = array_filter(
$acceptable_values,
'wpcf7_is_mailbox_list'
);
if ( count( $email_values ) === count( $acceptable_values ) ) {
return self::email | self::blank;
} else {
return self::email | self::text | self::blank;
}
}
return self::email | self::text | self::blank;
}
}
includes/css/styles-rtl.css 0000644 00000000230 14720664361 0012002 0 ustar 00 .wpcf7-not-valid-tip {
direction: rtl;
}
.use-floating-validation-tip .wpcf7-not-valid-tip {
right: 1em;
}
.wpcf7-list-item {
margin: 0 1em 0 0;
}
includes/css/styles.css 0000644 00000005516 14720664361 0011217 0 ustar 00 .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;
}
includes/contact-form.php 0000644 00000075126 14720664361 0011503 0 ustar 00 array(
'name' => __( 'Contact Forms', 'contact-form-7' ),
'singular_name' => __( 'Contact Form', 'contact-form-7' ),
),
'rewrite' => false,
'query_var' => false,
'public' => false,
'capability_type' => 'page',
'capabilities' => array(
'edit_post' => 'wpcf7_edit_contact_form',
'read_post' => 'wpcf7_read_contact_form',
'delete_post' => 'wpcf7_delete_contact_form',
'edit_posts' => 'wpcf7_edit_contact_forms',
'edit_others_posts' => 'wpcf7_edit_contact_forms',
'publish_posts' => 'wpcf7_edit_contact_forms',
'read_private_posts' => 'wpcf7_edit_contact_forms',
),
) );
}
/**
* Retrieves contact form data that match given conditions.
*
* @param string|array $args Optional. Arguments to be passed to WP_Query.
* @return array Array of WPCF7_ContactForm objects.
*/
public static function find( $args = '' ) {
$defaults = array(
'post_status' => 'any',
'posts_per_page' => -1,
'offset' => 0,
'orderby' => 'ID',
'order' => 'ASC',
);
$args = wp_parse_args( $args, $defaults );
$args['post_type'] = self::post_type;
$q = new WP_Query();
$posts = $q->query( $args );
self::$found_items = $q->found_posts;
$objs = array();
foreach ( (array) $posts as $post ) {
$objs[] = new self( $post );
}
return $objs;
}
/**
* Returns a contact form data filled by default template contents.
*
* @param string|array $options Optional. Contact form options.
* @return WPCF7_ContactForm A new contact form object.
*/
public static function get_template( $options = '' ) {
$options = wp_parse_args( $options, array(
'locale' => null,
'title' => __( 'Untitled', 'contact-form-7' ),
) );
if ( ! isset( $options['locale'] ) ) {
$options['locale'] = determine_locale();
}
$callback = static function ( $options ) {
$contact_form = new self;
$contact_form->title = $options['title'];
$contact_form->locale = $options['locale'];
$properties = $contact_form->get_properties();
foreach ( $properties as $key => $value ) {
$default_template = WPCF7_ContactFormTemplate::get_default( $key );
if ( isset( $default_template ) ) {
$properties[$key] = $default_template;
}
}
$contact_form->properties = $properties;
return $contact_form;
};
$contact_form = wpcf7_switch_locale(
$options['locale'],
$callback,
$options
);
self::$current = apply_filters( 'wpcf7_contact_form_default_pack',
$contact_form, $options
);
return self::$current;
}
/**
* Creates a WPCF7_ContactForm object and sets it as the current instance.
*
* @param WPCF7_ContactForm|WP_Post|int $post Object or post ID.
* @return WPCF7_ContactForm|null Contact form object. Null if unset.
*/
public static function get_instance( $post ) {
$contact_form = null;
if ( $post instanceof self ) {
$contact_form = $post;
} elseif ( ! empty( $post ) ) {
$post = get_post( $post );
if ( isset( $post ) and self::post_type === get_post_type( $post ) ) {
$contact_form = new self( $post );
}
}
return self::$current = $contact_form;
}
/**
* Generates a "unit-tag" for the given contact form ID.
*
* @return string Unit-tag.
*/
private static function generate_unit_tag( $id = 0 ) {
static $global_count = 0;
$global_count += 1;
if ( in_the_loop() ) {
$unit_tag = sprintf( 'wpcf7-f%1$d-p%2$d-o%3$d',
absint( $id ),
get_the_ID(),
$global_count
);
} else {
$unit_tag = sprintf( 'wpcf7-f%1$d-o%2$d',
absint( $id ),
$global_count
);
}
return $unit_tag;
}
/**
* Constructor.
*/
private function __construct( $post = null ) {
$post = get_post( $post );
if ( $post
and self::post_type === get_post_type( $post ) ) {
$this->id = $post->ID;
$this->name = $post->post_name;
$this->title = $post->post_title;
$this->locale = get_post_meta( $post->ID, '_locale', true );
$this->hash = get_post_meta( $post->ID, '_hash', true );
$this->construct_properties( $post );
$this->upgrade();
} else {
$this->construct_properties();
}
do_action( 'wpcf7_contact_form', $this );
}
/**
* Magic method for property overloading.
*/
public function __get( $name ) {
$message = __( '%1$s
property of a WPCF7_ContactForm
object is no longer accessible. Use %2$s
method instead.', 'contact-form-7' );
if ( 'id' === $name ) {
wp_trigger_error(
'',
sprintf( $message, 'id', 'id()' ),
E_USER_DEPRECATED
);
return $this->id;
} elseif ( 'title' === $name ) {
wp_trigger_error(
'',
sprintf( $message, 'title', 'title()' ),
E_USER_DEPRECATED
);
return $this->title;
} elseif ( $prop = $this->prop( $name ) ) {
wp_trigger_error(
'',
sprintf( $message, $name, 'prop(\'' . $name . '\')' ),
E_USER_DEPRECATED
);
return $prop;
}
}
/**
* Returns true if this contact form is not yet saved to the database.
*/
public function initial() {
return empty( $this->id );
}
/**
* Constructs contact form properties. This is called only once
* from the constructor.
*/
private function construct_properties( $post = null ) {
$builtin_properties = array(
'form' => '',
'mail' => array(),
'mail_2' => array(),
'messages' => array(),
'additional_settings' => '',
);
$properties = apply_filters(
'wpcf7_pre_construct_contact_form_properties',
$builtin_properties, $this
);
// Filtering out properties with invalid name
$properties = array_filter(
$properties,
static function ( $key ) {
$sanitized_key = sanitize_key( $key );
return $key === $sanitized_key;
},
ARRAY_FILTER_USE_KEY
);
foreach ( $properties as $name => $val ) {
$prop = $this->retrieve_property( $name );
if ( isset( $prop ) ) {
$properties[$name] = $prop;
}
}
$this->properties = $properties;
foreach ( $properties as $name => $val ) {
$properties[$name] = apply_filters(
"wpcf7_contact_form_property_{$name}",
$val, $this
);
}
$this->properties = $properties;
$properties = (array) apply_filters(
'wpcf7_contact_form_properties',
$properties, $this
);
$this->properties = $properties;
}
/**
* Retrieves contact form property of the specified name from the database.
*
* @param string $name Property name.
* @return array|string|null Property value. Null if property does not exist.
*/
private function retrieve_property( $name ) {
$property = null;
if ( ! $this->initial() ) {
$post_id = $this->id;
if ( metadata_exists( 'post', $post_id, '_' . $name ) ) {
$property = get_post_meta( $post_id, '_' . $name, true );
} elseif ( metadata_exists( 'post', $post_id, $name ) ) {
$property = get_post_meta( $post_id, $name, true );
}
}
return $property;
}
/**
* Returns the value for the given property name.
*
* @param string $name Property name.
* @return array|string|null Property value. Null if property does not exist.
*/
public function prop( $name ) {
$props = $this->get_properties();
return isset( $props[$name] ) ? $props[$name] : null;
}
/**
* Returns all the properties.
*
* @return array This contact form's properties.
*/
public function get_properties() {
return (array) $this->properties;
}
/**
* Updates properties.
*
* @param array $properties New properties.
*/
public function set_properties( $properties ) {
$defaults = $this->get_properties();
$properties = wp_parse_args( $properties, $defaults );
$properties = array_intersect_key( $properties, $defaults );
$this->properties = $properties;
}
/**
* Returns ID of this contact form.
*
* @return int The ID.
*/
public function id() {
return $this->id;
}
/**
* Returns unit-tag for this contact form.
*
* @return string Unit-tag.
*/
public function unit_tag() {
return $this->unit_tag;
}
/**
* Returns name (slug) of this contact form.
*
* @return string Name.
*/
public function name() {
return $this->name;
}
/**
* Returns title of this contact form.
*
* @return string Title.
*/
public function title() {
return $this->title;
}
/**
* Set a title for this contact form.
*
* @param string $title Title.
*/
public function set_title( $title ) {
$title = strip_tags( $title );
$title = trim( $title );
if ( '' === $title ) {
$title = __( 'Untitled', 'contact-form-7' );
}
$this->title = $title;
}
/**
* Returns the locale code of this contact form.
*
* @return string Locale code. Empty string if no valid locale is set.
*/
public function locale() {
if ( wpcf7_is_valid_locale( $this->locale ) ) {
return $this->locale;
} else {
return '';
}
}
/**
* Sets a locale for this contact form.
*
* @param string $locale Locale code.
*/
public function set_locale( $locale ) {
$locale = trim( $locale );
if ( wpcf7_is_valid_locale( $locale ) ) {
$this->locale = $locale;
} else {
$this->locale = 'en_US';
}
}
/**
* Retrieves the random hash string tied to this contact form.
*
* @param int $length Length of hash string.
* @return string Hash string unique to this contact form.
*/
public function hash( $length = 7 ) {
return substr( $this->hash, 0, absint( $length ) );
}
/**
* Returns the specified shortcode attribute value.
*
* @param string $name Shortcode attribute name.
* @return string|null Attribute value. Null if the attribute does not exist.
*/
public function shortcode_attr( $name ) {
if ( isset( $this->shortcode_atts[$name] ) ) {
return (string) $this->shortcode_atts[$name];
}
}
/**
* Returns true if this contact form is identical to the submitted one.
*/
public function is_posted() {
if ( ! WPCF7_Submission::get_instance() ) {
return false;
}
if ( empty( $_POST['_wpcf7_unit_tag'] ) ) {
return false;
}
return $this->unit_tag() === $_POST['_wpcf7_unit_tag'];
}
/**
* Generates HTML that represents a form.
*
* @param string|array $options Optional. Form options.
* @return string HTML output.
*/
public function form_html( $options = '' ) {
$options = wp_parse_args( $options, array(
'html_id' => '',
'html_name' => '',
'html_title' => '',
'html_class' => '',
'output' => 'form',
) );
$this->shortcode_atts = $options;
if ( 'raw_form' == $options['output'] ) {
return sprintf(
'
%s
',
esc_html( $this->prop( 'form' ) )
);
}
if ( $this->is_true( 'subscribers_only' )
and ! current_user_can( 'wpcf7_submit', $this->id() ) ) {
$notice = __(
"This contact form is available only for logged in users.",
'contact-form-7'
);
$notice = sprintf(
'%s
', esc_html( $notice ) ); return apply_filters( 'wpcf7_subscribers_only_notice', $notice, $this ); } $this->unit_tag = self::generate_unit_tag( $this->id ); $action_url = wpcf7_get_request_uri(); if ( $frag = strstr( $action_url, '#' ) ) { $action_url = substr( $action_url, 0, -strlen( $frag ) ); } $action_url .= '#' . $this->unit_tag(); $action_url = apply_filters( 'wpcf7_form_action_url', $action_url ); if ( str_starts_with( $action_url, '//' ) or ! str_starts_with( $action_url, '/' ) and ! str_starts_with( $action_url, home_url() ) ) { return sprintf( '%1$s %2$s
', esc_html( __( 'Error:', 'contact-form-7' ) ), esc_html( __( "Invalid action URL is detected.", 'contact-form-7' ) ) ); } $lang_tag = str_replace( '_', '-', $this->locale ); if ( preg_match( '/^([a-z]+-[a-z]+)-/i', $lang_tag, $matches ) ) { $lang_tag = $matches[1]; } $html = "\n" . sprintf( '%s
', esc_html( $primary_response ) ); $validation_errors = sprintf( '%1$s %2$s
', 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( $data = '', $context = 'save' ) { $data = wp_parse_args( $data, array( 'id' => -1, 'title' => null, 'locale' => null, 'form' => null, 'mail' => null, 'mail_2' => null, 'messages' => null, 'additional_settings' => null, ) ); $data = wp_unslash( $data ); $data['id'] = (int) $data['id']; if ( -1 == $data['id'] ) { $contact_form = WPCF7_ContactForm::get_template(); } else { $contact_form = wpcf7_contact_form( $data['id'] ); } if ( empty( $contact_form ) ) { return false; } if ( null !== $data['title'] ) { $contact_form->set_title( $data['title'] ); } if ( null !== $data['locale'] ) { $contact_form->set_locale( $data['locale'] ); } $properties = array(); if ( null !== $data['form'] ) { $properties['form'] = wpcf7_sanitize_form( $data['form'] ); } if ( null !== $data['mail'] ) { $properties['mail'] = wpcf7_sanitize_mail( $data['mail'] ); $properties['mail']['active'] = true; } if ( null !== $data['mail_2'] ) { $properties['mail_2'] = wpcf7_sanitize_mail( $data['mail_2'] ); } if ( null !== $data['messages'] ) { $properties['messages'] = wpcf7_sanitize_messages( $data['messages'] ); } if ( null !== $data['additional_settings'] ) { $properties['additional_settings'] = wpcf7_sanitize_additional_settings( $data['additional_settings'] ); } $contact_form->set_properties( $properties ); do_action( 'wpcf7_save_contact_form', $contact_form, $data, $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(), ) ) ); } includes/shortcodes.php 0000644 00000005226 14720664361 0011256 0 ustar 00 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 ); } } includes/config-validator/messages.php 0000644 00000002230 14720664361 0014130 0 ustar 00 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; } } includes/config-validator/additional-settings.php 0000644 00000001306 14720664361 0016272 0 ustar 00 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' ); } } } } includes/config-validator/actions.php 0000644 00000001203 14720664361 0013760 0 ustar 00 '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(); } } } includes/config-validator/mail.php 0000644 00000034377 14720664361 0013264 0 ustar 00 false, 'callback' => array( $this, 'replace_mail_tags_with_minimum_input_callback' ), ) ); $content = new WPCF7_MailTaggedText( $content, $options ); 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 = ''; // 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; } static $opcalcset = array(); if ( ! isset( $opcalcset[$this->contact_form->id()] ) ) { $opcalcset[$this->contact_form->id()] = new WPCF7_MailTag_OutputCalculator( $this->contact_form ); } $opcalc = $opcalcset[$this->contact_form->id()]; $op = $opcalc->calc_output( $mail_tag ); if ( WPCF7_MailTag_OutputCalculator::email === $op ) { return $example_email; } elseif ( ! ( WPCF7_MailTag_OutputCalculator::blank & $op ) ) { return $example_text; } else { return $example_blank; } } /** * 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; } } includes/config-validator/form.php 0000644 00000016456 14720664361 0013303 0 ustar 00 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 PHP’s 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 = '%%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 = '%(?:)%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; } } includes/config-validator/validator.php 0000644 00000020137 14720664361 0014314 0 ustar 00 null, 'exclude' => null, ) ); $this->contact_form = $contact_form; if ( isset( $options['include'] ) ) { $this->include = (array) $options['include']; } if ( isset( $options['exclude'] ) ) { $this->exclude = (array) $options['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( $options = '' ) { $options = wp_parse_args( $options, 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 ( $options['section'] and $key !== $options['section'] and preg_replace( '/\..*$/', '', $key, 1 ) !== $options['section'] ) { continue; } foreach ( $errors as $error ) { if ( empty( $error ) ) { continue; } if ( $options['code'] and $error['code'] !== $options['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 ); } } } } } includes/file.php 0000644 00000024236 14720664361 0010022 0 ustar 00 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( $options['schema'] ) and isset( $options['name'] ) ) { $context = array( 'file' => true, 'field' => $options['name'], ); foreach ( $options['schema']->validate( $context ) as $result ) { 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, $options ); $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, "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
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
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
if it exists. $this->end_tag( 'p' ); } if ( 'dd' === $tag_name or 'dt' === $tag_name ) { // Close