| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706 |
- <?php
- class WPCF7_ConfigValidator {
- const error = 100;
- const error_maybe_empty = 101;
- const error_invalid_mailbox_syntax = 102;
- const error_email_not_in_site_domain = 103;
- const error_html_in_message = 104;
- const error_multiple_controls_in_label = 105;
- const error_file_not_found = 106;
- const error_unavailable_names = 107;
- const error_invalid_mail_header = 108;
- const error_deprecated_settings = 109;
- const error_file_not_in_content_dir = 110;
- const error_unavailable_html_elements = 111;
- const error_attachments_overweight = 112;
- public static function get_doc_link( $error_code = '' ) {
- $url = __( 'https://contactform7.com/configuration-errors/',
- 'contact-form-7' );
- if ( '' !== $error_code ) {
- $error_code = strtr( $error_code, '_', '-' );
- $url = sprintf( '%s/%s', untrailingslashit( $url ), $error_code );
- }
- return esc_url( $url );
- }
- private $contact_form;
- private $errors = array();
- public function __construct( WPCF7_ContactForm $contact_form ) {
- $this->contact_form = $contact_form;
- }
- public function contact_form() {
- return $this->contact_form;
- }
- public function is_valid() {
- return ! $this->count_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;
- }
- 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;
- }
- 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;
- }
- public function get_default_message( $code ) {
- switch ( $code ) {
- case self::error_maybe_empty:
- return __( "There is a possible empty field.", 'contact-form-7' );
- case self::error_invalid_mailbox_syntax:
- return __( "Invalid mailbox syntax is used.", 'contact-form-7' );
- case self::error_email_not_in_site_domain:
- return __( "Sender email address does not belong to the site domain.", 'contact-form-7' );
- case self::error_html_in_message:
- return __( "HTML tags are used in a message.", 'contact-form-7' );
- case self::error_multiple_controls_in_label:
- return __( "Multiple form controls are in a single label element.", 'contact-form-7' );
- case self::error_invalid_mail_header:
- return __( "There are invalid mail header fields.", 'contact-form-7' );
- case self::error_deprecated_settings:
- return __( "Deprecated settings are used.", 'contact-form-7' );
- default:
- return '';
- }
- }
- public function add_error( $section, $code, $args = '' ) {
- $args = wp_parse_args( $args, array(
- 'message' => '',
- 'params' => array(),
- ) );
- if ( ! isset( $this->errors[$section] ) ) {
- $this->errors[$section] = array();
- }
- $this->errors[$section][] = array( 'code' => $code, 'args' => $args );
- return true;
- }
- 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] );
- }
- }
- public function validate() {
- $this->errors = array();
- $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();
- }
- public function save() {
- if ( $this->contact_form->initial() ) {
- return;
- }
- delete_post_meta( $this->contact_form->id(), '_config_errors' );
- if ( $this->errors ) {
- update_post_meta( $this->contact_form->id(), '_config_errors',
- $this->errors );
- }
- }
- public function restore() {
- $config_errors = get_post_meta(
- $this->contact_form->id(), '_config_errors', true );
- foreach ( (array) $config_errors as $section => $errors ) {
- if ( empty( $errors ) ) {
- continue;
- }
- if ( ! is_array( $errors ) ) { // for back-compat
- $code = $errors;
- $this->add_error( $section, $code );
- } else {
- foreach ( (array) $errors as $error ) {
- if ( ! empty( $error['code'] ) ) {
- $code = $error['code'];
- $args = isset( $error['args'] ) ? $error['args'] : '';
- $this->add_error( $section, $code, $args );
- }
- }
- }
- }
- }
- public function replace_mail_tags_with_minimum_input( $matches ) {
- // allow [[foo]] syntax for escaping a tag
- if ( $matches[1] == '[' && $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 ( '_user_' == substr( $field_name, 0, 6 ) ) {
- return $this->contact_form->is_true( 'subscribers_only' )
- ? $example_text
- : $example_blank;
- } elseif ( '_' == substr( $field_name, 0, 1 ) ) {
- return '_email' == substr( $field_name, -6 )
- ? $example_email
- : $example_text;
- }
- }
- return $tag;
- }
- public function validate_form() {
- $section = 'form.body';
- $form = $this->contact_form->prop( 'form' );
- $this->detect_multiple_controls_in_label( $section, $form );
- $this->detect_unavailable_names( $section, $form );
- $this->detect_unavailable_html_elements( $section, $form );
- }
- 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 $this->add_error( $section,
- self::error_multiple_controls_in_label, array(
- 'link' => self::get_doc_link( 'multiple_controls_in_label' ),
- )
- );
- }
- }
- }
- }
- return false;
- }
- 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 ) {
- $ng_names = array_unique( $ng_names );
- return $this->add_error( $section,
- self::error_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 ) ),
- 'link' => self::get_doc_link( 'unavailable_names' ),
- )
- );
- }
- return false;
- }
- public function detect_unavailable_html_elements( $section, $content ) {
- $pattern = '%(?:<form[\s\t>]|</form>)%i';
- if ( preg_match( $pattern, $content ) ) {
- return $this->add_error( $section,
- self::error_unavailable_html_elements,
- array(
- 'message' => __( "Unavailable HTML elements are used in the form template.", 'contact-form-7' ),
- 'link' => self::get_doc_link( 'unavailable_html_elements' ),
- )
- );
- }
- return false;
- }
- public function validate_mail( $template = 'mail' ) {
- $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' => '',
- ) );
- $callback = array( $this, 'replace_mail_tags_with_minimum_input' );
- $subject = $components['subject'];
- $subject = new WPCF7_MailTaggedText( $subject,
- array( 'callback' => $callback ) );
- $subject = $subject->replace_tags();
- $subject = wpcf7_strip_newline( $subject );
- $this->detect_maybe_empty( sprintf( '%s.subject', $template ), $subject );
- $sender = $components['sender'];
- $sender = new WPCF7_MailTaggedText( $sender,
- array( 'callback' => $callback ) );
- $sender = $sender->replace_tags();
- $sender = wpcf7_strip_newline( $sender );
- if ( ! $this->detect_invalid_mailbox_syntax( sprintf( '%s.sender', $template ), $sender )
- and ! wpcf7_is_email_in_site_domain( $sender ) ) {
- $this->add_error( sprintf( '%s.sender', $template ),
- self::error_email_not_in_site_domain, array(
- 'link' => self::get_doc_link( 'email_not_in_site_domain' ),
- )
- );
- }
- $recipient = $components['recipient'];
- $recipient = new WPCF7_MailTaggedText( $recipient,
- array( 'callback' => $callback ) );
- $recipient = $recipient->replace_tags();
- $recipient = wpcf7_strip_newline( $recipient );
- $this->detect_invalid_mailbox_syntax(
- sprintf( '%s.recipient', $template ), $recipient );
- $additional_headers = $components['additional_headers'];
- $additional_headers = new WPCF7_MailTaggedText( $additional_headers,
- array( 'callback' => $callback ) );
- $additional_headers = $additional_headers->replace_tags();
- $additional_headers = explode( "\n", $additional_headers );
- $mailbox_header_types = array( 'reply-to', 'cc', 'bcc' );
- $invalid_mail_header_exists = false;
- foreach ( $additional_headers as $header ) {
- $header = trim( $header );
- if ( '' === $header ) {
- continue;
- }
- if ( ! preg_match( '/^([0-9A-Za-z-]+):(.*)$/', $header, $matches ) ) {
- $invalid_mail_header_exists = true;
- } else {
- $header_name = $matches[1];
- $header_value = trim( $matches[2] );
- if ( in_array( strtolower( $header_name ), $mailbox_header_types ) ) {
- $this->detect_invalid_mailbox_syntax(
- sprintf( '%s.additional_headers', $template ),
- $header_value, array(
- 'message' =>
- __( "Invalid mailbox syntax is used in the %name% field.", 'contact-form-7' ),
- 'params' => array( 'name' => $header_name ) ) );
- } elseif ( empty( $header_value ) ) {
- $invalid_mail_header_exists = true;
- }
- }
- }
- if ( $invalid_mail_header_exists ) {
- $this->add_error( sprintf( '%s.additional_headers', $template ),
- self::error_invalid_mail_header, array(
- 'link' => self::get_doc_link( 'invalid_mail_header' ),
- )
- );
- }
- $body = $components['body'];
- $body = new WPCF7_MailTaggedText( $body,
- array( 'callback' => $callback ) );
- $body = $body->replace_tags();
- $this->detect_maybe_empty( sprintf( '%s.body', $template ), $body );
- if ( '' !== $components['attachments'] ) {
- $attachables = array();
- $tags = $this->contact_form->scan_form_tags(
- array( 'type' => array( 'file', 'file*' ) )
- );
- foreach ( $tags as $tag ) {
- $name = $tag->name;
- if ( false === strpos( $components['attachments'], "[{$name}]" ) ) {
- continue;
- }
- $limit = (int) $tag->get_limit_option();
- if ( empty( $attachables[$name] )
- or $attachables[$name] < $limit ) {
- $attachables[$name] = $limit;
- }
- }
- $total_size = array_sum( $attachables );
- $has_file_not_found = false;
- $has_file_not_in_content_dir = false;
- foreach ( explode( "\n", $components['attachments'] ) as $line ) {
- $line = trim( $line );
- if ( '' === $line
- or '[' == substr( $line, 0, 1 ) ) {
- continue;
- }
- $has_file_not_found = $this->detect_file_not_found(
- sprintf( '%s.attachments', $template ), $line
- );
- if ( ! $has_file_not_found
- and ! $has_file_not_in_content_dir ) {
- $has_file_not_in_content_dir = $this->detect_file_not_in_content_dir(
- sprintf( '%s.attachments', $template ), $line
- );
- }
- if ( ! $has_file_not_found ) {
- $path = path_join( WP_CONTENT_DIR, $line );
- $total_size += (int) @filesize( $path );
- }
- }
- $max = 25 * 1024 * 1024; // 25 MB
- if ( $max < $total_size ) {
- $this->add_error( sprintf( '%s.attachments', $template ),
- self::error_attachments_overweight,
- array(
- 'message' => __( "The total size of attachment files is too large.", 'contact-form-7' ),
- 'link' => self::get_doc_link( 'attachments_overweight' ),
- )
- );
- }
- }
- }
- public function detect_invalid_mailbox_syntax( $section, $content, $args = '' ) {
- $args = wp_parse_args( $args, array(
- 'link' => self::get_doc_link( 'invalid_mailbox_syntax' ),
- 'message' => '',
- 'params' => array(),
- ) );
- if ( ! wpcf7_is_mailbox_list( $content ) ) {
- return $this->add_error( $section,
- self::error_invalid_mailbox_syntax, $args );
- }
- return false;
- }
- public function detect_maybe_empty( $section, $content ) {
- if ( '' === $content ) {
- return $this->add_error( $section,
- self::error_maybe_empty, array(
- 'link' => self::get_doc_link( 'maybe_empty' ),
- )
- );
- }
- return false;
- }
- public function detect_file_not_found( $section, $content ) {
- $path = path_join( WP_CONTENT_DIR, $content );
- if ( ! is_readable( $path )
- or ! is_file( $path ) ) {
- return $this->add_error( $section,
- self::error_file_not_found,
- array(
- 'message' =>
- __( "Attachment file does not exist at %path%.", 'contact-form-7' ),
- 'params' => array( 'path' => $content ),
- 'link' => self::get_doc_link( 'file_not_found' ),
- )
- );
- }
- return false;
- }
- 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 $this->add_error( $section,
- self::error_file_not_in_content_dir,
- array(
- 'message' =>
- __( "It is not allowed to use files outside the wp-content directory.", 'contact-form-7' ),
- 'link' => self::get_doc_link( 'file_not_in_content_dir' ),
- )
- );
- }
- return false;
- }
- 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 );
- $this->detect_html_in_message( $section, $message );
- }
- }
- public function detect_html_in_message( $section, $content ) {
- $stripped = wp_strip_all_tags( $content );
- if ( $stripped != $content ) {
- return $this->add_error( $section,
- self::error_html_in_message,
- array(
- 'link' => self::get_doc_link( 'html_in_message' ),
- )
- );
- }
- return false;
- }
- public function validate_additional_settings() {
- $deprecated_settings_used =
- $this->contact_form->additional_setting( 'on_sent_ok' ) ||
- $this->contact_form->additional_setting( 'on_submit' );
- if ( $deprecated_settings_used ) {
- return $this->add_error( 'additional_settings.body',
- self::error_deprecated_settings,
- array(
- 'link' => self::get_doc_link( 'deprecated_settings' ),
- )
- );
- }
- }
- }
|