Contact Form 7 - Version 5.5

Version Description

https://contactform7.com/contact-form-7-55/

Download this release

Release Info

Developer takayukister
Plugin Icon 128x128 Contact Form 7
Version 5.5
Comparing to
See all releases

Code changes from version 5.4.2 to 5.5

admin/admin.php CHANGED
@@ -181,22 +181,6 @@ function wpcf7_admin_enqueue_scripts( $hook_suffix ) {
181
  }
182
 
183
 
184
- add_action(
185
- 'doing_dark_mode',
186
- 'wpcf7_dark_mode_support',
187
- 10, 1
188
- );
189
-
190
- function wpcf7_dark_mode_support( $user_id ) {
191
- wp_enqueue_style( 'contact-form-7-admin-dark-mode',
192
- wpcf7_plugin_url( 'admin/css/styles-dark-mode.css' ),
193
- array( 'contact-form-7-admin' ),
194
- WPCF7_VERSION,
195
- 'screen'
196
- );
197
- }
198
-
199
-
200
  add_filter(
201
  'set_screen_option_wpcf7_contact_forms_per_page',
202
  function ( $result, $option, $value ) {
@@ -515,6 +499,17 @@ function wpcf7_admin_integration_page() {
515
 
516
  <h1><?php echo esc_html( __( 'Integration with External API', 'contact-form-7' ) ); ?></h1>
517
 
 
 
 
 
 
 
 
 
 
 
 
518
  <?php
519
  do_action( 'wpcf7_admin_warnings',
520
  'wpcf7-integration', wpcf7_current_action(), $service
181
  }
182
 
183
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
184
  add_filter(
185
  'set_screen_option_wpcf7_contact_forms_per_page',
186
  function ( $result, $option, $value ) {
499
 
500
  <h1><?php echo esc_html( __( 'Integration with External API', 'contact-form-7' ) ); ?></h1>
501
 
502
+ <p><?php
503
+ echo sprintf(
504
+ /* translators: %s: link labeled 'Integration with external APIs' */
505
+ esc_html( __( "You can expand the possibilities of your contact forms by integrating them with external services. For details, see %s.", 'contact-form-7' ) ),
506
+ wpcf7_link(
507
+ __( 'https://contactform7.com/integration-with-external-apis/', 'contact-form-7' ),
508
+ __( 'Integration with external APIs', 'contact-form-7' )
509
+ )
510
+ );
511
+ ?></p>
512
+
513
  <?php
514
  do_action( 'wpcf7_admin_warnings',
515
  'wpcf7-integration', wpcf7_current_action(), $service
admin/css/styles-dark-mode.css DELETED
@@ -1,72 +0,0 @@
1
- #wpcf7-contact-form-list-table span.shortcode input,
2
- #wpcf7-contact-form-editor span.shortcode input {
3
- color: #fff;
4
- }
5
-
6
- div.config-error, span.config-error, ul.config-error {
7
- color: #bbc8d4;
8
- }
9
-
10
- .keyboard-interaction {
11
- color: #bbc8d4;
12
- }
13
-
14
- #contact-form-editor .contact-form-editor-panel {
15
- background-color: #32373c;
16
- }
17
-
18
- #contact-form-editor-tabs {
19
- border-bottom: 1px solid #aaa;
20
- }
21
-
22
- #contact-form-editor-tabs li {
23
- border: 1px solid #ccc;
24
- border-bottom: 1px solid #aaa;
25
- background-color: #37444c;
26
- }
27
-
28
- #contact-form-editor-tabs li:hover {
29
- background-color: #000;
30
- }
31
-
32
- #contact-form-editor-tabs li.ui-tabs-active,
33
- #contact-form-editor-tabs li.ui-tabs-active:hover {
34
- border-top: 1px solid #aaa;
35
- border-right: 1px solid #aaa;
36
- border-left: 1px solid #aaa;
37
- border-bottom: 1px solid #32373c;
38
- background-color: #32373c;
39
- }
40
-
41
- #contact-form-editor-tabs li a {
42
- color: #bbc8d4;
43
- }
44
-
45
- #contact-form-editor-tabs li.ui-tabs-active a {
46
- color: #fff;
47
- }
48
-
49
- #contact-form-editor-tabs li a:hover {
50
- color: #fff;
51
- }
52
-
53
- .contact-form-editor-box-mail span.mailtag {
54
- color: #ddd;
55
- }
56
-
57
- .contact-form-editor-box-mail span.mailtag.used {
58
- color: #999;
59
- }
60
-
61
- #mail-panel .contact-form-editor-box-mail table.form-table tr th,
62
- #mail-panel .contact-form-editor-box-mail table.form-table tr td {
63
- background-color: #32373c;
64
- }
65
-
66
- div.wrap#wpcf7-integration .card.active {
67
- border-color: #00a0d2;
68
- }
69
-
70
- div.wrap#wpcf7-integration .card .infobox {
71
- color: #aaa;
72
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
admin/edit-contact-form.php CHANGED
@@ -247,7 +247,13 @@ if ( $post ) :
247
  ),
248
  );
249
 
250
- $additional_settings = trim( $post->prop( 'additional_settings' ) );
 
 
 
 
 
 
251
  $additional_settings = explode( "\n", $additional_settings );
252
  $additional_settings = array_filter( $additional_settings );
253
  $additional_settings = count( $additional_settings );
247
  ),
248
  );
249
 
250
+ $additional_settings = $post->prop( 'additional_settings' );
251
+
252
+ if ( ! is_scalar( $additional_settings ) ) {
253
+ $additional_settings = '';
254
+ }
255
+
256
+ $additional_settings = trim( $additional_settings );
257
  $additional_settings = explode( "\n", $additional_settings );
258
  $additional_settings = array_filter( $additional_settings );
259
  $additional_settings = count( $additional_settings );
admin/includes/config-validator.php CHANGED
@@ -9,7 +9,7 @@ function wpcf7_admin_init_bulk_cv() {
9
  }
10
 
11
  $result = WPCF7::get_option( 'bulk_validate' );
12
- $last_important_update = '5.1.5';
13
 
14
  if ( ! empty( $result['version'] )
15
  and version_compare( $last_important_update, $result['version'], '<=' ) ) {
@@ -17,10 +17,14 @@ function wpcf7_admin_init_bulk_cv() {
17
  }
18
 
19
  add_filter( 'wpcf7_admin_menu_change_notice',
20
- 'wpcf7_admin_menu_change_notice_bulk_cv', 10, 1 );
 
 
21
 
22
  add_action( 'wpcf7_admin_warnings',
23
- 'wpcf7_admin_warnings_bulk_cv', 5, 3 );
 
 
24
  }
25
 
26
  function wpcf7_admin_menu_change_notice_bulk_cv( $counts ) {
9
  }
10
 
11
  $result = WPCF7::get_option( 'bulk_validate' );
12
+ $last_important_update = WPCF7_ConfigValidator::last_important_update;
13
 
14
  if ( ! empty( $result['version'] )
15
  and version_compare( $last_important_update, $result['version'], '<=' ) ) {
17
  }
18
 
19
  add_filter( 'wpcf7_admin_menu_change_notice',
20
+ 'wpcf7_admin_menu_change_notice_bulk_cv',
21
+ 10, 1
22
+ );
23
 
24
  add_action( 'wpcf7_admin_warnings',
25
+ 'wpcf7_admin_warnings_bulk_cv',
26
+ 5, 3
27
+ );
28
  }
29
 
30
  function wpcf7_admin_menu_change_notice_bulk_cv( $counts ) {
admin/includes/welcome-panel.php CHANGED
@@ -1,10 +1,210 @@
1
  <?php
2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  function wpcf7_welcome_panel() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  $classes = 'welcome-panel';
5
 
6
  $vers = (array) get_user_meta( get_current_user_id(),
7
- 'wpcf7_hide_welcome_panel_on', true );
 
8
 
9
  if ( wpcf7_version_grep( wpcf7_version( 'only_major=1' ), $vers ) ) {
10
  $classes .= ' hidden';
@@ -17,84 +217,32 @@ function wpcf7_welcome_panel() {
17
 
18
  <div class="welcome-panel-content">
19
  <div class="welcome-panel-column-container">
 
20
 
21
- <div class="welcome-panel-column">
22
- <h3><span class="dashicons dashicons-shield" aria-hidden="true"></span> <?php echo esc_html( __( "Getting spammed? You have protection.", 'contact-form-7' ) ); ?></h3>
23
-
24
- <p><?php echo esc_html( __( "Spammers target everything; your contact forms aren&#8217;t an exception. Before you get spammed, protect your contact forms with the powerful anti-spam features Contact Form 7 provides.", 'contact-form-7' ) ); ?></p>
25
-
26
- <p><?php
27
- echo sprintf(
28
- /* translators: links labeled 1: 'Akismet', 2: 'reCAPTCHA', 3: 'disallowed list' */
29
- esc_html( __( 'Contact Form 7 supports spam-filtering with %1$s. Intelligent %2$s blocks annoying spambots. Plus, using %3$s, you can block messages containing specified keywords or those sent from specified IP addresses.', 'contact-form-7' ) ),
30
- wpcf7_link(
31
- __( 'https://contactform7.com/spam-filtering-with-akismet/', 'contact-form-7' ),
32
- __( 'Akismet', 'contact-form-7' )
33
- ),
34
- wpcf7_link(
35
- __( 'https://contactform7.com/recaptcha/', 'contact-form-7' ),
36
- __( 'reCAPTCHA', 'contact-form-7' )
37
- ),
38
- wpcf7_link(
39
- __( 'https://contactform7.com/comment-blacklist/', 'contact-form-7' ),
40
- __( 'disallowed list', 'contact-form-7' )
41
- )
42
- );
43
- ?></p>
44
- </div>
45
-
46
- <?php if ( defined( 'FLAMINGO_VERSION' ) ) : ?>
47
- <div class="welcome-panel-column">
48
- <h3><span class="dashicons dashicons-megaphone" aria-hidden="true"></span> <?php echo esc_html( __( "Contact Form 7 needs your support.", 'contact-form-7' ) ); ?></h3>
49
-
50
- <p><?php echo esc_html( __( "It is hard to continue development and support for this plugin without contributions from users like you.", 'contact-form-7' ) ); ?></p>
51
-
52
- <p><?php
53
- echo sprintf(
54
- /* translators: %s: link labeled 'making a donation' */
55
- esc_html( __( 'If you enjoy using Contact Form 7 and find it useful, please consider %s.', 'contact-form-7' ) ),
56
- wpcf7_link(
57
- __( 'https://contactform7.com/donate/', 'contact-form-7' ),
58
- __( 'making a donation', 'contact-form-7' )
59
- )
60
- );
61
- ?></p>
62
-
63
- <p><?php echo esc_html( __( "Your donation will help encourage and support the plugin&#8217;s continued development and better user support.", 'contact-form-7' ) ); ?></p>
64
- </div>
65
- <?php else: ?>
66
- <div class="welcome-panel-column">
67
- <h3><span class="dashicons dashicons-editor-help" aria-hidden="true"></span> <?php echo esc_html( __( "Before you cry over spilt mail&#8230;", 'contact-form-7' ) ); ?></h3>
68
-
69
- <p><?php echo esc_html( __( "Contact Form 7 doesn&#8217;t store submitted messages anywhere. Therefore, you may lose important messages forever if your mail server has issues or you make a mistake in mail configuration.", 'contact-form-7' ) ); ?></p>
70
-
71
- <p><?php
72
- echo sprintf(
73
- /* translators: %s: link labeled 'Flamingo' */
74
- esc_html( __( 'Install a message storage plugin before this happens to you. %s saves all messages through contact forms into the database. Flamingo is a free WordPress plugin created by the same author as Contact Form 7.', 'contact-form-7' ) ),
75
- wpcf7_link(
76
- __( 'https://contactform7.com/save-submitted-messages-with-flamingo/', 'contact-form-7' ),
77
- __( 'Flamingo', 'contact-form-7' )
78
- )
79
- );
80
- ?></p>
81
- </div>
82
- <?php endif; ?>
83
 
 
84
  </div>
85
  </div>
86
  </div>
87
  <?php
88
  }
89
 
90
- add_action( 'wp_ajax_wpcf7-update-welcome-panel',
91
- 'wpcf7_admin_ajax_welcome_panel', 10, 0 );
 
 
 
 
92
 
93
  function wpcf7_admin_ajax_welcome_panel() {
94
  check_ajax_referer( 'wpcf7-welcome-panel-nonce', 'welcomepanelnonce' );
95
 
96
  $vers = get_user_meta( get_current_user_id(),
97
- 'wpcf7_hide_welcome_panel_on', true );
 
98
 
99
  if ( empty( $vers ) or ! is_array( $vers ) ) {
100
  $vers = array();
@@ -102,12 +250,58 @@ function wpcf7_admin_ajax_welcome_panel() {
102
 
103
  if ( empty( $_POST['visible'] ) ) {
104
  $vers[] = wpcf7_version( 'only_major=1' );
 
 
105
  }
106
 
107
  $vers = array_unique( $vers );
108
 
109
  update_user_meta( get_current_user_id(),
110
- 'wpcf7_hide_welcome_panel_on', $vers );
 
111
 
112
  wp_die( 1 );
113
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <?php
2
 
3
+ abstract class WPCF7_WelcomePanelColumn {
4
+
5
+ abstract protected function icon();
6
+ abstract protected function title();
7
+ abstract protected function content();
8
+
9
+ public function print() {
10
+ $icon = sprintf(
11
+ '<span class="dashicons dashicons-%s" aria-hidden="true"></span>',
12
+ esc_attr( $this->icon() )
13
+ );
14
+
15
+ $title = sprintf(
16
+ '<h3>%1$s %2$s</h3>',
17
+ $icon,
18
+ $this->title()
19
+ );
20
+
21
+ $content = $this->content();
22
+
23
+ if ( is_array( $content ) ) {
24
+ $content = implode( "\n\n", $content );
25
+ }
26
+
27
+ $content = wp_kses_post( $content );
28
+ $content = wptexturize( $content );
29
+ $content = convert_chars( $content );
30
+ $content = wpautop( $content );
31
+
32
+ echo "\n";
33
+ echo '<div class="welcome-panel-column">';
34
+ echo $title;
35
+ echo $content;
36
+ echo '</div>';
37
+ }
38
+ }
39
+
40
+
41
+ class WPCF7_WelcomePanelColumn_AntiSpam extends WPCF7_WelcomePanelColumn {
42
+
43
+ protected function icon() {
44
+ return 'shield';
45
+ }
46
+
47
+ protected function title() {
48
+ return esc_html(
49
+ __( "Getting spammed? You have protection.", 'contact-form-7' )
50
+ );
51
+ }
52
+
53
+ protected function content() {
54
+ return array(
55
+ esc_html( __( "Spammers target everything; your contact forms aren&#8217;t an exception. Before you get spammed, protect your contact forms with the powerful anti-spam features Contact Form 7 provides.", 'contact-form-7' ) ),
56
+ sprintf(
57
+ /* translators: links labeled 1: 'Akismet', 2: 'reCAPTCHA', 3: 'disallowed list' */
58
+ esc_html( __( 'Contact Form 7 supports spam-filtering with %1$s. Intelligent %2$s blocks annoying spambots. Plus, using %3$s, you can block messages containing specified keywords or those sent from specified IP addresses.', 'contact-form-7' ) ),
59
+ wpcf7_link(
60
+ __( 'https://contactform7.com/spam-filtering-with-akismet/', 'contact-form-7' ),
61
+ __( 'Akismet', 'contact-form-7' )
62
+ ),
63
+ wpcf7_link(
64
+ __( 'https://contactform7.com/recaptcha/', 'contact-form-7' ),
65
+ __( 'reCAPTCHA', 'contact-form-7' )
66
+ ),
67
+ wpcf7_link(
68
+ __( 'https://contactform7.com/comment-blacklist/', 'contact-form-7' ),
69
+ __( 'disallowed list', 'contact-form-7' )
70
+ )
71
+ ),
72
+ );
73
+ }
74
+ }
75
+
76
+
77
+ class WPCF7_WelcomePanelColumn_Donation extends WPCF7_WelcomePanelColumn {
78
+
79
+ protected function icon() {
80
+ return 'megaphone';
81
+ }
82
+
83
+ protected function title() {
84
+ return esc_html(
85
+ __( "Contact Form 7 needs your support.", 'contact-form-7' )
86
+ );
87
+ }
88
+
89
+ protected function content() {
90
+ return array(
91
+ esc_html( __( "It is hard to continue development and support for this plugin without contributions from users like you.", 'contact-form-7' ) ),
92
+ sprintf(
93
+ /* translators: %s: link labeled 'making a donation' */
94
+ esc_html( __( 'If you enjoy using Contact Form 7 and find it useful, please consider %s.', 'contact-form-7' ) ),
95
+ wpcf7_link(
96
+ __( 'https://contactform7.com/donate/', 'contact-form-7' ),
97
+ __( 'making a donation', 'contact-form-7' )
98
+ )
99
+ ),
100
+ esc_html( __( "Your donation will help encourage and support the plugin&#8217;s continued development and better user support.", 'contact-form-7' ) ),
101
+ );
102
+ }
103
+ }
104
+
105
+
106
+ class WPCF7_WelcomePanelColumn_Flamingo extends WPCF7_WelcomePanelColumn {
107
+
108
+ protected function icon() {
109
+ return 'editor-help';
110
+ }
111
+
112
+ protected function title() {
113
+ return esc_html(
114
+ __( "Before you cry over spilt mail&#8230;", 'contact-form-7' )
115
+ );
116
+ }
117
+
118
+ protected function content() {
119
+ return array(
120
+ esc_html( __( "Contact Form 7 doesn&#8217;t store submitted messages anywhere. Therefore, you may lose important messages forever if your mail server has issues or you make a mistake in mail configuration.", 'contact-form-7' ) ),
121
+ sprintf(
122
+ /* translators: %s: link labeled 'Flamingo' */
123
+ esc_html( __( 'Install a message storage plugin before this happens to you. %s saves all messages through contact forms into the database. Flamingo is a free WordPress plugin created by the same author as Contact Form 7.', 'contact-form-7' ) ),
124
+ wpcf7_link(
125
+ __( 'https://contactform7.com/save-submitted-messages-with-flamingo/', 'contact-form-7' ),
126
+ __( 'Flamingo', 'contact-form-7' )
127
+ )
128
+ ),
129
+ );
130
+ }
131
+ }
132
+
133
+
134
+ class WPCF7_WelcomePanelColumn_Integration extends WPCF7_WelcomePanelColumn {
135
+
136
+ protected function icon() {
137
+ return 'superhero-alt';
138
+ }
139
+
140
+ protected function title() {
141
+ return esc_html(
142
+ __( "You have strong allies to back you up.", 'contact-form-7' )
143
+ );
144
+ }
145
+
146
+ protected function content() {
147
+ return array(
148
+ sprintf(
149
+ /* translators: 1: link labeled 'Sendinblue', 2: link labeled 'Constant Contact' */
150
+ esc_html( __( 'Your contact forms will become more powerful and versatile by integrating them with external APIs. With CRM and email marketing services, you can build your own contact lists (%1$s and %2$s).', 'contact-form-7' ) ),
151
+ wpcf7_link(
152
+ __( 'https://contactform7.com/sendinblue-integration/', 'contact-form-7' ),
153
+ __( 'Sendinblue', 'contact-form-7' )
154
+ ),
155
+ wpcf7_link(
156
+ __( 'https://contactform7.com/constant-contact-integration/', 'contact-form-7' ),
157
+ __( 'Constant Contact', 'contact-form-7' )
158
+ )
159
+ ),
160
+ sprintf(
161
+ /* translators: 1: link labeled 'reCAPTCHA', 2: link labeled 'Stripe' */
162
+ esc_html( __( 'With help from cloud-based machine learning, anti-spam services will protect your forms (%1$s). Even payment services are natively supported (%2$s).', 'contact-form-7' ) ),
163
+ wpcf7_link(
164
+ __( 'https://contactform7.com/recaptcha/', 'contact-form-7' ),
165
+ __( 'reCAPTCHA', 'contact-form-7' )
166
+ ),
167
+ wpcf7_link(
168
+ __( 'https://contactform7.com/stripe-integration/', 'contact-form-7' ),
169
+ __( 'Stripe', 'contact-form-7' )
170
+ )
171
+ ),
172
+ );
173
+ }
174
+ }
175
+
176
+
177
  function wpcf7_welcome_panel() {
178
+ $columns = array();
179
+
180
+ $flamingo_is_active = defined( 'FLAMINGO_VERSION' );
181
+
182
+ $sendinblue_is_active = false;
183
+
184
+ if ( class_exists( 'WPCF7_Sendinblue' )
185
+ and $sendinblue = WPCF7_Sendinblue::get_instance() ) {
186
+ $sendinblue_is_active = $sendinblue->is_active();
187
+ }
188
+
189
+ if ( $flamingo_is_active and $sendinblue_is_active ) {
190
+ $columns[] = new WPCF7_WelcomePanelColumn_AntiSpam();
191
+ $columns[] = new WPCF7_WelcomePanelColumn_Donation();
192
+ } elseif ( $flamingo_is_active ) {
193
+ $columns[] = new WPCF7_WelcomePanelColumn_Integration();
194
+ $columns[] = new WPCF7_WelcomePanelColumn_AntiSpam();
195
+ } elseif ( $sendinblue_is_active ) {
196
+ $columns[] = new WPCF7_WelcomePanelColumn_Flamingo();
197
+ $columns[] = new WPCF7_WelcomePanelColumn_AntiSpam();
198
+ } else {
199
+ $columns[] = new WPCF7_WelcomePanelColumn_Flamingo();
200
+ $columns[] = new WPCF7_WelcomePanelColumn_Integration();
201
+ }
202
+
203
  $classes = 'welcome-panel';
204
 
205
  $vers = (array) get_user_meta( get_current_user_id(),
206
+ 'wpcf7_hide_welcome_panel_on', true
207
+ );
208
 
209
  if ( wpcf7_version_grep( wpcf7_version( 'only_major=1' ), $vers ) ) {
210
  $classes .= ' hidden';
217
 
218
  <div class="welcome-panel-content">
219
  <div class="welcome-panel-column-container">
220
+ <?php
221
 
222
+ foreach ( $columns as $column ) {
223
+ $column->print();
224
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
225
 
226
+ ?>
227
  </div>
228
  </div>
229
  </div>
230
  <?php
231
  }
232
 
233
+
234
+ add_action(
235
+ 'wp_ajax_wpcf7-update-welcome-panel',
236
+ 'wpcf7_admin_ajax_welcome_panel',
237
+ 10, 0
238
+ );
239
 
240
  function wpcf7_admin_ajax_welcome_panel() {
241
  check_ajax_referer( 'wpcf7-welcome-panel-nonce', 'welcomepanelnonce' );
242
 
243
  $vers = get_user_meta( get_current_user_id(),
244
+ 'wpcf7_hide_welcome_panel_on', true
245
+ );
246
 
247
  if ( empty( $vers ) or ! is_array( $vers ) ) {
248
  $vers = array();
250
 
251
  if ( empty( $_POST['visible'] ) ) {
252
  $vers[] = wpcf7_version( 'only_major=1' );
253
+ } else {
254
+ $vers = array_diff( $vers, array( wpcf7_version( 'only_major=1' ) ) );
255
  }
256
 
257
  $vers = array_unique( $vers );
258
 
259
  update_user_meta( get_current_user_id(),
260
+ 'wpcf7_hide_welcome_panel_on', $vers
261
+ );
262
 
263
  wp_die( 1 );
264
  }
265
+
266
+
267
+ add_filter(
268
+ 'screen_settings',
269
+ 'wpcf7_welcome_panel_screen_settings',
270
+ 10, 2
271
+ );
272
+
273
+ function wpcf7_welcome_panel_screen_settings( $screen_settings, $screen ) {
274
+
275
+ if ( 'toplevel_page_wpcf7' !== $screen->id ) {
276
+ return $screen_settings;
277
+ }
278
+
279
+ $vers = get_user_meta( get_current_user_id(),
280
+ 'wpcf7_hide_welcome_panel_on', true
281
+ );
282
+
283
+ $checkbox_id = 'wpcf7-welcome-panel-show';
284
+ $checked = ! in_array( wpcf7_version( 'only_major=1' ), $vers );
285
+
286
+ $checkbox = sprintf(
287
+ '<input %s />',
288
+ wpcf7_format_atts( array(
289
+ 'id' => $checkbox_id,
290
+ 'type' => 'checkbox',
291
+ 'checked' => $checked ? 'checked' : null,
292
+ ) )
293
+ );
294
+
295
+ $screen_settings .= sprintf( '
296
+ <fieldset class="wpcf7-welcome-panel-options">
297
+ <legend>%1$s</legend>
298
+ <label for="%2$s">%3$s %4$s</label>
299
+ </fieldset>',
300
+ esc_html( __( 'Welcome panel', 'contact-form-7' ) ),
301
+ esc_attr( $checkbox_id ),
302
+ $checkbox,
303
+ esc_html( __( 'Show welcome panel', 'contact-form-7' ) )
304
+ );
305
+
306
+ return $screen_settings;
307
+ }
admin/js/scripts.js CHANGED
@@ -22,6 +22,17 @@
22
  event.preventDefault();
23
  welcomePanel.addClass( 'hidden' );
24
  updateWelcomePanel( 0 );
 
 
 
 
 
 
 
 
 
 
 
25
  } );
26
 
27
  $( '#contact-form-editor' ).tabs( {
22
  event.preventDefault();
23
  welcomePanel.addClass( 'hidden' );
24
  updateWelcomePanel( 0 );
25
+ $( '#wpcf7-welcome-panel-show' ).prop( 'checked', false );
26
+ } );
27
+
28
+ $( '#wpcf7-welcome-panel-show' ).click( function( event ) {
29
+ if ( this.checked ) {
30
+ welcomePanel.removeClass( 'hidden' );
31
+ updateWelcomePanel( 1 );
32
+ } else {
33
+ welcomePanel.addClass( 'hidden' );
34
+ updateWelcomePanel( 0 );
35
+ }
36
  } );
37
 
38
  $( '#contact-form-editor' ).tabs( {
includes/block-editor/index.js CHANGED
@@ -1 +1 @@
1
- !function(e){var t={};function c(r){if(t[r])return t[r].exports;var n=t[r]={i:r,l:!1,exports:{}};return e[r].call(n.exports,n,n.exports,c),n.l=!0,n.exports}c.m=e,c.c=t,c.d=function(e,t,r){c.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},c.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},c.t=function(e,t){if(1&t&&(e=c(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(c.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)c.d(r,n,function(t){return e[t]}.bind(null,n));return r},c.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return c.d(t,"a",t),t},c.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},c.p="",c(c.s=6)}([function(e,t){e.exports=window.wp.element},function(e,t){e.exports=window.wp.i18n},function(e,t){e.exports=window.wp.blocks},function(e,t){e.exports=window.wp.apiFetch},function(e,t){e.exports=window.wp.compose},function(e,t){e.exports=window.wp.components},function(e,t,c){"use strict";c.r(t);var r=c(0),n=c(1),o=c(2),a=Object(r.createElement)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 242.5 239.46"},Object(r.createElement)("defs",null,Object(r.createElement)("clipPath",{id:"clip-path",transform:"translate(1.72)"},Object(r.createElement)("circle",{className:"cls-1",cx:"119.73",cy:"119.73",r:"116.15",fill:"none"}))),Object(r.createElement)("g",{id:"Layer_2","data-name":"Layer 2"},Object(r.createElement)("g",{id:"Layer_1","data-name":"Layer 1"},Object(r.createElement)("g",{className:"cls-2",clipPath:"url(#clip-path)"},Object(r.createElement)("circle",{className:"cls-3",cx:"121.45",cy:"119.73",r:"116.15",fill:"#33c6f4"}),Object(r.createElement)("path",{className:"cls-4",d:"M239.32,167.79c-53.41-24-108.37-91.46-113-94.55s-10.84.77-10.84.77c-3.87-6.19-10.06.77-10.06.77C76.77,123.55.14,170.11.14,170.11S36.94,237.79,122,237.79C208.48,237.79,239.32,167.79,239.32,167.79Z",transform:"translate(1.72)",fill:"#1b447e"}),Object(r.createElement)("path",{className:"cls-5",d:"M67.48,116.58s15.48-7,12.38,4.65-15.48,28.64-11.61,29.41S83,140.58,86.06,142.12s5.42.78,3.87,6.2-3.1,9.29,0,9.29,5.42-7,9.29-13.94,10.06-3.87,12.38-1.55,9.29,15.49,14.71,13.94,8.51-8.52,6.19-24,1.55-20.12,1.55-20.12,4.64-2.32,13.16,8.51,24,27.09,26.31,26.32-10.83-17.8-7.74-19.35,15.48,2.32,21.68,7.74c0,0,2.12,8.87,2.12.36L126.31,73.24,115.47,74l-10.06.77S80.64,111.94,67.48,116.58Z",transform:"translate(1.72)",fill:"#fff"}),Object(r.createElement)("path",{className:"cls-6",d:"M239.32,170.11c-53.41-24-108.37-93.78-113-96.87s-10.84.77-10.84.77c-3.87-6.19-10.06.77-10.06.77C76.77,123.55.14,170.11.14,170.11",transform:"translate(1.72)",fill:"none",stroke:"#221e1f",strokeMiterlimit:"10",strokeWidth:"8px"})),Object(r.createElement)("circle",{className:"cls-6",cx:"121.45",cy:"119.73",r:"116.15",fill:"none",stroke:"#1b447e",strokeMiterlimit:"10",strokeWidth:"8px"})))),l=c(3),i=c.n(l),s=c(4),f=c(5);const m=new Map;i()({path:"contact-form-7/v1/contact-forms?per_page=20"}).then(e=>{Object.entries(e).forEach(([e,t])=>{m.set(t.id,t)})});var u={from:[{type:"shortcode",tag:"contact-form-7",attributes:{id:{type:"integer",shortcode:function(e){var t=e.named.id;return parseInt(t)}},title:{type:"string",shortcode:function(e){return e.named.title}}}}],to:[{type:"block",blocks:["core/shortcode"],transform:function(e){return Object(o.createBlock)("core/shortcode",{text:'[contact-form-7 id="'.concat(e.id,'" title="').concat(e.title,'"]')})}}]};Object(o.registerBlockType)("contact-form-7/contact-form-selector",{title:Object(n.__)("Contact Form 7","contact-form-7"),description:Object(n.__)("Insert a contact form you have created with Contact Form 7.","contact-form-7"),category:"widgets",attributes:{id:{type:"integer"},title:{type:"string"}},icon:a,transforms:u,edit:function e({attributes:t,setAttributes:c}){if(!m.size&&!t.id)return Object(r.createElement)("div",{className:"components-placeholder"},Object(r.createElement)("p",null,Object(n.__)("No contact forms were found. Create a contact form first.","contact-form-7")));const o=Array.from(m.values(),e=>({value:e.id,label:e.title}));if(t.id)o.length||o.push({value:t.id,label:t.title});else{const e=o[0];t={id:parseInt(e.value),title:e.label}}const a="contact-form-7-contact-form-selector-"+Object(s.useInstanceId)(e);return Object(r.createElement)("div",{className:"components-placeholder"},Object(r.createElement)("label",{htmlFor:a,className:"components-placeholder__label"},Object(n.__)("Select a contact form:","contact-form-7")),Object(r.createElement)(f.SelectControl,{id:a,options:o,value:t.id,onChange:e=>c({id:parseInt(e),title:m.get(parseInt(e)).title})}))},save:function(e){var t=e.attributes;return Object(r.createElement)("div",null,'[contact-form-7 id="',t.id,'" title="',t.title,'"]')}})}]);
1
+ !function(){"use strict";var e={n:function(t){var r=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(r,{a:r}),r},d:function(t,r){for(var c in r)e.o(r,c)&&!e.o(t,c)&&Object.defineProperty(t,c,{enumerable:!0,get:r[c]})},o:function(e,t){return Object.prototype.hasOwnProperty.call(e,t)}},t=window.wp.element,r=window.wp.i18n,c=window.wp.blocks,n=(0,t.createElement)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 242.5 239.46"},(0,t.createElement)("defs",null,(0,t.createElement)("clipPath",{id:"clip-path",transform:"translate(1.72)"},(0,t.createElement)("circle",{className:"cls-1",cx:"119.73",cy:"119.73",r:"116.15",fill:"none"}))),(0,t.createElement)("g",{id:"Layer_2","data-name":"Layer 2"},(0,t.createElement)("g",{id:"Layer_1","data-name":"Layer 1"},(0,t.createElement)("g",{className:"cls-2",clipPath:"url(#clip-path)"},(0,t.createElement)("circle",{className:"cls-3",cx:"121.45",cy:"119.73",r:"116.15",fill:"#33c6f4"}),(0,t.createElement)("path",{className:"cls-4",d:"M239.32,167.79c-53.41-24-108.37-91.46-113-94.55s-10.84.77-10.84.77c-3.87-6.19-10.06.77-10.06.77C76.77,123.55.14,170.11.14,170.11S36.94,237.79,122,237.79C208.48,237.79,239.32,167.79,239.32,167.79Z",transform:"translate(1.72)",fill:"#1b447e"}),(0,t.createElement)("path",{className:"cls-5",d:"M67.48,116.58s15.48-7,12.38,4.65-15.48,28.64-11.61,29.41S83,140.58,86.06,142.12s5.42.78,3.87,6.2-3.1,9.29,0,9.29,5.42-7,9.29-13.94,10.06-3.87,12.38-1.55,9.29,15.49,14.71,13.94,8.51-8.52,6.19-24,1.55-20.12,1.55-20.12,4.64-2.32,13.16,8.51,24,27.09,26.31,26.32-10.83-17.8-7.74-19.35,15.48,2.32,21.68,7.74c0,0,2.12,8.87,2.12.36L126.31,73.24,115.47,74l-10.06.77S80.64,111.94,67.48,116.58Z",transform:"translate(1.72)",fill:"#fff"}),(0,t.createElement)("path",{className:"cls-6",d:"M239.32,170.11c-53.41-24-108.37-93.78-113-96.87s-10.84.77-10.84.77c-3.87-6.19-10.06.77-10.06.77C76.77,123.55.14,170.11.14,170.11",transform:"translate(1.72)",fill:"none",stroke:"#221e1f",strokeMiterlimit:"10",strokeWidth:"8px"})),(0,t.createElement)("circle",{className:"cls-6",cx:"121.45",cy:"119.73",r:"116.15",fill:"none",stroke:"#1b447e",strokeMiterlimit:"10",strokeWidth:"8px"})))),a=window.wp.apiFetch,o=e.n(a),l=window.wp.compose,s=window.wp.components;const i=new Map;o()({path:"contact-form-7/v1/contact-forms?per_page=20"}).then((e=>{Object.entries(e).forEach((([e,t])=>{i.set(t.id,t)}))}));var m={from:[{type:"shortcode",tag:"contact-form-7",attributes:{id:{type:"integer",shortcode:function(e){var t=e.named.id;return parseInt(t)}},title:{type:"string",shortcode:function(e){return e.named.title}}}}],to:[{type:"block",blocks:["core/shortcode"],transform:function(e){return(0,c.createBlock)("core/shortcode",{text:'[contact-form-7 id="'.concat(e.id,'" title="').concat(e.title,'"]')})}}]};(0,c.registerBlockType)("contact-form-7/contact-form-selector",{title:(0,r.__)("Contact Form 7","contact-form-7"),description:(0,r.__)("Insert a contact form you have created with Contact Form 7.","contact-form-7"),category:"widgets",attributes:{id:{type:"integer"},title:{type:"string"}},icon:n,transforms:m,edit:function e({attributes:c,setAttributes:n}){if(!i.size&&!c.id)return(0,t.createElement)("div",{className:"components-placeholder"},(0,t.createElement)("p",null,(0,r.__)("No contact forms were found. Create a contact form first.","contact-form-7")));const a=Array.from(i.values(),(e=>({value:e.id,label:e.title})));if(c.id)a.length||a.push({value:c.id,label:c.title});else{const e=a[0];c={id:parseInt(e.value),title:e.label}}const o=`contact-form-7-contact-form-selector-${(0,l.useInstanceId)(e)}`;return(0,t.createElement)("div",{className:"components-placeholder"},(0,t.createElement)("label",{htmlFor:o,className:"components-placeholder__label"},(0,r.__)("Select a contact form:","contact-form-7")),(0,t.createElement)(s.SelectControl,{id:o,options:a,value:c.id,onChange:e=>n({id:parseInt(e),title:i.get(parseInt(e)).title})}))},save:function(e){var r=e.attributes;return(0,t.createElement)("div",null,'[contact-form-7 id="',r.id,'" title="',r.title,'"]')}})}();
includes/config-validator.php CHANGED
@@ -2,6 +2,8 @@
2
 
3
  class WPCF7_ConfigValidator {
4
 
 
 
5
  const error = 100;
6
  const error_maybe_empty = 101;
7
  const error_invalid_mailbox_syntax = 102;
@@ -15,10 +17,12 @@ class WPCF7_ConfigValidator {
15
  const error_file_not_in_content_dir = 110;
16
  const error_unavailable_html_elements = 111;
17
  const error_attachments_overweight = 112;
 
18
 
19
  public static function get_doc_link( $error_code = '' ) {
20
  $url = __( 'https://contactform7.com/configuration-errors/',
21
- 'contact-form-7' );
 
22
 
23
  if ( '' !== $error_code ) {
24
  $error_code = strtr( $error_code, '_', '-' );
@@ -326,6 +330,7 @@ class WPCF7_ConfigValidator {
326
  $this->detect_multiple_controls_in_label( $section, $form );
327
  $this->detect_unavailable_names( $section, $form );
328
  $this->detect_unavailable_html_elements( $section, $form );
 
329
  }
330
 
331
  public function detect_multiple_controls_in_label( $section, $content ) {
@@ -378,11 +383,14 @@ class WPCF7_ConfigValidator {
378
  'name', 'category_name', 'tag', 'feed', 'author_name', 'static',
379
  'pagename', 'page_id', 'error', 'attachment', 'attachment_id',
380
  'subpost', 'subpost_id', 'preview', 'robots', 'taxonomy', 'term',
381
- 'cpage', 'post_type', 'embed' );
 
382
 
383
  $form_tags_manager = WPCF7_FormTagsManager::get_instance();
384
- $ng_named_tags = $form_tags_manager->filter( $content,
385
- array( 'name' => $public_query_vars ) );
 
 
386
 
387
  $ng_names = array();
388
 
@@ -424,6 +432,28 @@ class WPCF7_ConfigValidator {
424
  return false;
425
  }
426
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
427
  public function validate_mail( $template = 'mail' ) {
428
  $components = (array) $this->contact_form->prop( $template );
429
 
2
 
3
  class WPCF7_ConfigValidator {
4
 
5
+ const last_important_update = '5.5';
6
+
7
  const error = 100;
8
  const error_maybe_empty = 101;
9
  const error_invalid_mailbox_syntax = 102;
17
  const error_file_not_in_content_dir = 110;
18
  const error_unavailable_html_elements = 111;
19
  const error_attachments_overweight = 112;
20
+ const error_dots_in_names = 113;
21
 
22
  public static function get_doc_link( $error_code = '' ) {
23
  $url = __( 'https://contactform7.com/configuration-errors/',
24
+ 'contact-form-7'
25
+ );
26
 
27
  if ( '' !== $error_code ) {
28
  $error_code = strtr( $error_code, '_', '-' );
330
  $this->detect_multiple_controls_in_label( $section, $form );
331
  $this->detect_unavailable_names( $section, $form );
332
  $this->detect_unavailable_html_elements( $section, $form );
333
+ $this->detect_dots_in_names( $section, $form );
334
  }
335
 
336
  public function detect_multiple_controls_in_label( $section, $content ) {
383
  'name', 'category_name', 'tag', 'feed', 'author_name', 'static',
384
  'pagename', 'page_id', 'error', 'attachment', 'attachment_id',
385
  'subpost', 'subpost_id', 'preview', 'robots', 'taxonomy', 'term',
386
+ 'cpage', 'post_type', 'embed',
387
+ );
388
 
389
  $form_tags_manager = WPCF7_FormTagsManager::get_instance();
390
+
391
+ $ng_named_tags = $form_tags_manager->filter( $content, array(
392
+ 'name' => $public_query_vars,
393
+ ) );
394
 
395
  $ng_names = array();
396
 
432
  return false;
433
  }
434
 
435
+ public function detect_dots_in_names( $section, $content ) {
436
+ $form_tags_manager = WPCF7_FormTagsManager::get_instance();
437
+
438
+ $tags = $form_tags_manager->filter( $content, array(
439
+ 'feature' => 'name-attr',
440
+ ) );
441
+
442
+ foreach ( $tags as $tag ) {
443
+ if ( false !== strpos( $tag->raw_name, '.' ) ) {
444
+ return $this->add_error( $section,
445
+ self::error_dots_in_names,
446
+ array(
447
+ 'message' => __( "Dots are used in form-tag names.", 'contact-form-7' ),
448
+ 'link' => self::get_doc_link( 'dots_in_names' ),
449
+ )
450
+ );
451
+ }
452
+ }
453
+
454
+ return false;
455
+ }
456
+
457
  public function validate_mail( $template = 'mail' ) {
458
  $components = (array) $this->contact_form->prop( $template );
459
 
includes/contact-form-functions.php CHANGED
@@ -222,6 +222,11 @@ function wpcf7_sanitize_form( $input, $default = '' ) {
222
  }
223
 
224
  $output = trim( $input );
 
 
 
 
 
225
  return $output;
226
  }
227
 
@@ -246,6 +251,11 @@ function wpcf7_sanitize_mail( $input, $defaults = array() ) {
246
  $output['sender'] = trim( $input['sender'] );
247
  $output['recipient'] = trim( $input['recipient'] );
248
  $output['body'] = trim( $input['body'] );
 
 
 
 
 
249
  $output['additional_headers'] = '';
250
 
251
  $headers = str_replace( "\r\n", "\n", $input['additional_headers'] );
222
  }
223
 
224
  $output = trim( $input );
225
+
226
+ if ( ! current_user_can( 'unfiltered_html' ) ) {
227
+ $output = wpcf7_kses( $output, 'form' );
228
+ }
229
+
230
  return $output;
231
  }
232
 
251
  $output['sender'] = trim( $input['sender'] );
252
  $output['recipient'] = trim( $input['recipient'] );
253
  $output['body'] = trim( $input['body'] );
254
+
255
+ if ( ! current_user_can( 'unfiltered_html' ) ) {
256
+ $output['body'] = wpcf7_kses( $output['body'], 'mail' );
257
+ }
258
+
259
  $output['additional_headers'] = '';
260
 
261
  $headers = str_replace( "\r\n", "\n", $input['additional_headers'] );
includes/contact-form.php CHANGED
@@ -17,14 +17,30 @@ class WPCF7_ContactForm {
17
  private $scanned_form_tags;
18
  private $shortcode_atts = array();
19
 
 
 
 
 
 
 
20
  public static function count() {
21
  return self::$found_items;
22
  }
23
 
 
 
 
 
 
 
24
  public static function get_current() {
25
  return self::$current;
26
  }
27
 
 
 
 
 
28
  public static function register_post_type() {
29
  register_post_type( self::post_type, array(
30
  'labels' => array(
@@ -47,6 +63,13 @@ class WPCF7_ContactForm {
47
  ) );
48
  }
49
 
 
 
 
 
 
 
 
50
  public static function find( $args = '' ) {
51
  $defaults = array(
52
  'post_status' => 'any',
@@ -74,6 +97,13 @@ class WPCF7_ContactForm {
74
  return $objs;
75
  }
76
 
 
 
 
 
 
 
 
77
  public static function get_template( $args = '' ) {
78
  $args = wp_parse_args( $args, array(
79
  'locale' => '',
@@ -112,6 +142,12 @@ class WPCF7_ContactForm {
112
  return $contact_form;
113
  }
114
 
 
 
 
 
 
 
115
  public static function get_instance( $post ) {
116
  $post = get_post( $post );
117
 
@@ -123,6 +159,12 @@ class WPCF7_ContactForm {
123
  return self::$current = new self( $post );
124
  }
125
 
 
 
 
 
 
 
126
  private static function generate_unit_tag( $id = 0 ) {
127
  static $global_count = 0;
128
 
@@ -144,6 +186,10 @@ class WPCF7_ContactForm {
144
  return $unit_tag;
145
  }
146
 
 
 
 
 
147
  private function __construct( $post = null ) {
148
  $post = get_post( $post );
149
 
@@ -171,6 +217,10 @@ class WPCF7_ContactForm {
171
  do_action( 'wpcf7_contact_form', $this );
172
  }
173
 
 
 
 
 
174
  public function __get( $name ) {
175
  $message = __( '<code>%1$s</code> property of a <code>WPCF7_ContactForm</code> object is <strong>no longer accessible</strong>. Use <code>%2$s</code> method instead.', 'contact-form-7' );
176
 
@@ -204,15 +254,32 @@ class WPCF7_ContactForm {
204
  }
205
  }
206
 
 
 
 
 
207
  public function initial() {
208
  return empty( $this->id );
209
  }
210
 
 
 
 
 
 
 
 
211
  public function prop( $name ) {
212
  $props = $this->get_properties();
213
  return isset( $props[$name] ) ? $props[$name] : null;
214
  }
215
 
 
 
 
 
 
 
216
  public function get_properties() {
217
  $properties = (array) $this->properties;
218
 
@@ -224,12 +291,20 @@ class WPCF7_ContactForm {
224
  'additional_settings' => '',
225
  ) );
226
 
227
- $properties = (array) apply_filters( 'wpcf7_contact_form_properties',
228
- $properties, $this );
 
 
229
 
230
  return $properties;
231
  }
232
 
 
 
 
 
 
 
233
  public function set_properties( $properties ) {
234
  $defaults = $this->get_properties();
235
 
@@ -239,22 +314,52 @@ class WPCF7_ContactForm {
239
  $this->properties = $properties;
240
  }
241
 
 
 
 
 
 
 
242
  public function id() {
243
  return $this->id;
244
  }
245
 
 
 
 
 
 
 
246
  public function unit_tag() {
247
  return $this->unit_tag;
248
  }
249
 
 
 
 
 
 
 
250
  public function name() {
251
  return $this->name;
252
  }
253
 
 
 
 
 
 
 
254
  public function title() {
255
  return $this->title;
256
  }
257
 
 
 
 
 
 
 
258
  public function set_title( $title ) {
259
  $title = strip_tags( $title );
260
  $title = trim( $title );
@@ -266,6 +371,12 @@ class WPCF7_ContactForm {
266
  $this->title = $title;
267
  }
268
 
 
 
 
 
 
 
269
  public function locale() {
270
  if ( wpcf7_is_valid_locale( $this->locale ) ) {
271
  return $this->locale;
@@ -274,6 +385,12 @@ class WPCF7_ContactForm {
274
  }
275
  }
276
 
 
 
 
 
 
 
277
  public function set_locale( $locale ) {
278
  $locale = trim( $locale );
279
 
@@ -284,13 +401,23 @@ class WPCF7_ContactForm {
284
  }
285
  }
286
 
 
 
 
 
 
 
 
287
  public function shortcode_attr( $name ) {
288
  if ( isset( $this->shortcode_atts[$name] ) ) {
289
  return (string) $this->shortcode_atts[$name];
290
  }
291
  }
292
 
293
- // Return true if this form is the same one as currently POSTed.
 
 
 
294
  public function is_posted() {
295
  if ( ! WPCF7_Submission::get_instance() ) {
296
  return false;
@@ -303,8 +430,13 @@ class WPCF7_ContactForm {
303
  return $this->unit_tag() === $_POST['_wpcf7_unit_tag'];
304
  }
305
 
306
- /* Generating Form HTML */
307
 
 
 
 
 
 
 
308
  public function form_html( $args = '' ) {
309
  $args = wp_parse_args( $args, array(
310
  'html_id' => '',
@@ -316,18 +448,23 @@ class WPCF7_ContactForm {
316
  $this->shortcode_atts = $args;
317
 
318
  if ( 'raw_form' == $args['output'] ) {
319
- return '<pre class="wpcf7-raw-form"><code>'
320
- . esc_html( $this->prop( 'form' ) ) . '</code></pre>';
 
 
321
  }
322
 
323
  if ( $this->is_true( 'subscribers_only' )
324
  and ! current_user_can( 'wpcf7_submit', $this->id() ) ) {
325
  $notice = __(
326
  "This contact form is available only for logged in users.",
327
- 'contact-form-7' );
 
 
328
  $notice = sprintf(
329
  '<p class="wpcf7-subscribers-only">%s</p>',
330
- esc_html( $notice ) );
 
331
 
332
  return apply_filters( 'wpcf7_subscribers_only_notice', $notice, $this );
333
  }
@@ -364,10 +501,12 @@ class WPCF7_ContactForm {
364
  $url = apply_filters( 'wpcf7_form_action_url', $url );
365
 
366
  $id_attr = apply_filters( 'wpcf7_form_id_attr',
367
- preg_replace( '/[^A-Za-z0-9:._-]/', '', $args['html_id'] ) );
 
368
 
369
  $name_attr = apply_filters( 'wpcf7_form_name_attr',
370
- preg_replace( '/[^A-Za-z0-9:._-]/', '', $args['html_name'] ) );
 
371
 
372
  $class = 'wpcf7-form';
373
 
@@ -440,6 +579,10 @@ class WPCF7_ContactForm {
440
  return $html;
441
  }
442
 
 
 
 
 
443
  private function form_status_class_name( $status ) {
444
  switch ( $status ) {
445
  case 'init':
@@ -473,6 +616,10 @@ class WPCF7_ContactForm {
473
  return $class;
474
  }
475
 
 
 
 
 
476
  private function form_hidden_fields() {
477
  $hidden_fields = array(
478
  '_wpcf7' => $this->id(),
@@ -487,24 +634,31 @@ class WPCF7_ContactForm {
487
  $hidden_fields['_wpcf7_container_post'] = (int) get_the_ID();
488
  }
489
 
490
- if ( $this->nonce_is_active() && is_user_logged_in() ) {
491
  $hidden_fields['_wpnonce'] = wpcf7_create_nonce();
492
  }
493
 
494
  $hidden_fields += (array) apply_filters(
495
- 'wpcf7_form_hidden_fields', array() );
 
496
 
497
  $content = '';
498
 
499
  foreach ( $hidden_fields as $name => $value ) {
500
  $content .= sprintf(
501
  '<input type="hidden" name="%1$s" value="%2$s" />',
502
- esc_attr( $name ), esc_attr( $value ) ) . "\n";
 
 
503
  }
504
 
505
  return '<div style="display: none;">' . "\n" . $content . '</div>' . "\n";
506
  }
507
 
 
 
 
 
508
  public function form_response_output() {
509
  $status = 'init';
510
  $class = 'wpcf7-response-output';
@@ -535,6 +689,10 @@ class WPCF7_ContactForm {
535
  return $output;
536
  }
537
 
 
 
 
 
538
  public function screen_reader_response() {
539
  $primary_response = '';
540
  $validation_errors = array();
@@ -591,6 +749,12 @@ class WPCF7_ContactForm {
591
  return $output;
592
  }
593
 
 
 
 
 
 
 
594
  public function validation_error( $name ) {
595
  $error = '';
596
 
@@ -620,8 +784,12 @@ class WPCF7_ContactForm {
620
  return apply_filters( 'wpcf7_validation_error', $error, $name, $this );
621
  }
622
 
623
- /* Form Elements */
624
 
 
 
 
 
 
625
  public function replace_all_form_tags() {
626
  $manager = WPCF7_FormTagsManager::get_instance();
627
  $form = $this->prop( 'form' );
@@ -637,13 +805,29 @@ class WPCF7_ContactForm {
637
  return $form;
638
  }
639
 
 
 
 
 
 
 
 
 
640
  public function form_do_shortcode() {
641
  wpcf7_deprecated_function( __METHOD__, '4.6',
642
- 'WPCF7_ContactForm::replace_all_form_tags' );
 
643
 
644
  return $this->replace_all_form_tags();
645
  }
646
 
 
 
 
 
 
 
 
647
  public function scan_form_tags( $cond = null ) {
648
  $manager = WPCF7_FormTagsManager::get_instance();
649
 
@@ -656,6 +840,15 @@ class WPCF7_ContactForm {
656
  return $manager->filter( $tags, $cond );
657
  }
658
 
 
 
 
 
 
 
 
 
 
659
  public function form_scan_shortcode( $cond = null ) {
660
  wpcf7_deprecated_function( __METHOD__, '4.6',
661
  'WPCF7_ContactForm::scan_form_tags'
@@ -664,12 +857,25 @@ class WPCF7_ContactForm {
664
  return $this->scan_form_tags( $cond );
665
  }
666
 
 
 
 
 
 
 
667
  public function form_elements() {
668
  return apply_filters( 'wpcf7_form_elements',
669
  $this->replace_all_form_tags()
670
  );
671
  }
672
 
 
 
 
 
 
 
 
673
  public function collect_mail_tags( $args = '' ) {
674
  $manager = WPCF7_FormTagsManager::get_instance();
675
 
@@ -704,6 +910,12 @@ class WPCF7_ContactForm {
704
  return apply_filters( 'wpcf7_collect_mail_tags', $mailtags, $args, $this );
705
  }
706
 
 
 
 
 
 
 
707
  public function suggest_mail_tags( $for = 'mail' ) {
708
  $mail = wp_parse_args( $this->prop( $for ),
709
  array(
@@ -737,6 +949,13 @@ class WPCF7_ContactForm {
737
  }
738
  }
739
 
 
 
 
 
 
 
 
740
  public function submit( $args = '' ) {
741
  $args = wp_parse_args( $args, array(
742
  'skip_mail' =>
@@ -765,25 +984,12 @@ class WPCF7_ContactForm {
765
 
766
  $result = array(
767
  'contact_form_id' => $this->id(),
768
- 'status' => $submission->get_status(),
769
- 'message' => $submission->get_response(),
770
- 'demo_mode' => $this->in_demo_mode(),
771
  );
772
 
773
- if ( $submission->is( 'validation_failed' ) ) {
774
- $result['invalid_fields'] = $submission->get_invalid_fields();
775
- }
776
 
777
- switch ( $submission->get_status() ) {
778
- case 'init':
779
- case 'validation_failed':
780
- case 'acceptance_missing':
781
- case 'spam':
782
- $result['posted_data_hash'] = '';
783
- break;
784
- default:
785
- $result['posted_data_hash'] = $submission->get_posted_data_hash();
786
- break;
787
  }
788
 
789
  do_action( 'wpcf7_submit', $this, $result );
@@ -791,8 +997,14 @@ class WPCF7_ContactForm {
791
  return $result;
792
  }
793
 
794
- /* Message */
795
 
 
 
 
 
 
 
 
796
  public function message( $status, $filter = true ) {
797
  $messages = $this->prop( 'messages' );
798
  $message = isset( $messages[$status] ) ? $messages[$status] : '';
@@ -804,6 +1016,14 @@ class WPCF7_ContactForm {
804
  return $message;
805
  }
806
 
 
 
 
 
 
 
 
 
807
  public function filter_message( $message, $status = '' ) {
808
  $message = wpcf7_mail_replace_tags( $message );
809
  $message = apply_filters( 'wpcf7_display_message', $message, $status );
@@ -812,8 +1032,13 @@ class WPCF7_ContactForm {
812
  return $message;
813
  }
814
 
815
- /* Additional settings */
816
 
 
 
 
 
 
 
817
  public function pref( $name ) {
818
  $settings = $this->additional_setting( $name );
819
 
@@ -822,6 +1047,14 @@ class WPCF7_ContactForm {
822
  }
823
  }
824
 
 
 
 
 
 
 
 
 
825
  public function additional_setting( $name, $max = 1 ) {
826
  $settings = (array) explode( "\n", $this->prop( 'additional_settings' ) );
827
 
@@ -845,6 +1078,13 @@ class WPCF7_ContactForm {
845
  return $values;
846
  }
847
 
 
 
 
 
 
 
 
848
  public function is_true( $name ) {
849
  return in_array(
850
  $this->pref( $name ),
@@ -853,10 +1093,18 @@ class WPCF7_ContactForm {
853
  );
854
  }
855
 
 
 
 
 
856
  public function in_demo_mode() {
857
  return $this->is_true( 'demo_mode' );
858
  }
859
 
 
 
 
 
860
  public function nonce_is_active() {
861
  $is_active = WPCF7_VERIFY_NONCE;
862
 
@@ -867,8 +1115,10 @@ class WPCF7_ContactForm {
867
  return (bool) apply_filters( 'wpcf7_verify_nonce', $is_active, $this );
868
  }
869
 
870
- /* Upgrade */
871
 
 
 
 
872
  private function upgrade() {
873
  $mail = $this->prop( 'mail' );
874
 
@@ -892,10 +1142,15 @@ class WPCF7_ContactForm {
892
  $this->properties['messages'] = $messages;
893
  }
894
 
895
- /* Save */
896
 
 
 
 
 
 
897
  public function save() {
898
- $props = $this->get_properties();
 
899
 
900
  $post_content = implode( "\n", wpcf7_array_flatten( $props ) );
901
 
@@ -903,14 +1158,14 @@ class WPCF7_ContactForm {
903
  $post_id = wp_insert_post( array(
904
  'post_type' => self::post_type,
905
  'post_status' => 'publish',
906
- 'post_title' => $this->title,
907
  'post_content' => trim( $post_content ),
908
  ) );
909
  } else {
910
  $post_id = wp_update_post( array(
911
  'ID' => (int) $this->id,
912
  'post_status' => 'publish',
913
- 'post_title' => $this->title,
914
  'post_content' => trim( $post_content ),
915
  ) );
916
  }
@@ -918,7 +1173,8 @@ class WPCF7_ContactForm {
918
  if ( $post_id ) {
919
  foreach ( $props as $prop => $value ) {
920
  update_post_meta( $post_id, '_' . $prop,
921
- wpcf7_normalize_newline_deep( $value ) );
 
922
  }
923
 
924
  if ( wpcf7_is_valid_locale( $this->locale ) ) {
@@ -938,6 +1194,12 @@ class WPCF7_ContactForm {
938
  return $post_id;
939
  }
940
 
 
 
 
 
 
 
941
  public function copy() {
942
  $new = new self;
943
  $new->title = $this->title . '_copy';
@@ -947,6 +1209,10 @@ class WPCF7_ContactForm {
947
  return apply_filters( 'wpcf7_copy', $new, $this );
948
  }
949
 
 
 
 
 
950
  public function delete() {
951
  if ( $this->initial() ) {
952
  return;
@@ -960,9 +1226,14 @@ class WPCF7_ContactForm {
960
  return false;
961
  }
962
 
 
 
 
 
963
  public function shortcode( $args = '' ) {
964
  $args = wp_parse_args( $args, array(
965
- 'use_old_format' => false ) );
 
966
 
967
  $title = str_replace( array( '"', '[', ']' ), '', $this->title );
968
 
@@ -970,16 +1241,24 @@ class WPCF7_ContactForm {
970
  $old_unit_id = (int) get_post_meta( $this->id, '_old_cf7_unit_id', true );
971
 
972
  if ( $old_unit_id ) {
973
- $shortcode = sprintf( '[contact-form %1$d "%2$s"]', $old_unit_id, $title );
 
 
 
 
974
  } else {
975
  $shortcode = '';
976
  }
977
  } else {
978
- $shortcode = sprintf( '[contact-form-7 id="%1$d" title="%2$s"]',
979
- $this->id, $title );
 
 
 
980
  }
981
 
982
  return apply_filters( 'wpcf7_contact_form_shortcode',
983
- $shortcode, $args, $this );
 
984
  }
985
  }
17
  private $scanned_form_tags;
18
  private $shortcode_atts = array();
19
 
20
+
21
+ /**
22
+ * Returns count of contact forms found by the previous retrieval.
23
+ *
24
+ * @return int Count of contact forms.
25
+ */
26
  public static function count() {
27
  return self::$found_items;
28
  }
29
 
30
+
31
+ /**
32
+ * Returns the contact form that is currently processed.
33
+ *
34
+ * @return WPCF7_ContactForm Current contact form object.
35
+ */
36
  public static function get_current() {
37
  return self::$current;
38
  }
39
 
40
+
41
+ /**
42
+ * Registers the post type for contact forms.
43
+ */
44
  public static function register_post_type() {
45
  register_post_type( self::post_type, array(
46
  'labels' => array(
63
  ) );
64
  }
65
 
66
+
67
+ /**
68
+ * Retrieves contact form data that match given conditions.
69
+ *
70
+ * @param string|array $args Optional. Arguments to be passed to WP_Query.
71
+ * @return array Array of WPCF7_ContactForm objects.
72
+ */
73
  public static function find( $args = '' ) {
74
  $defaults = array(
75
  'post_status' => 'any',
97
  return $objs;
98
  }
99
 
100
+
101
+ /**
102
+ * Returns a contact form data filled by default template contents.
103
+ *
104
+ * @param string|array $args Optional. Contact form options.
105
+ * @return WPCF7_ContactForm A new contact form object.
106
+ */
107
  public static function get_template( $args = '' ) {
108
  $args = wp_parse_args( $args, array(
109
  'locale' => '',
142
  return $contact_form;
143
  }
144
 
145
+
146
+ /**
147
+ * Returns an instance of WPCF7_ContactForm.
148
+ *
149
+ * @return WPCF7_ContactForm A new contact form object.
150
+ */
151
  public static function get_instance( $post ) {
152
  $post = get_post( $post );
153
 
159
  return self::$current = new self( $post );
160
  }
161
 
162
+
163
+ /**
164
+ * Generates a "unit-tag" for the given contact form ID.
165
+ *
166
+ * @return string Unit-tag.
167
+ */
168
  private static function generate_unit_tag( $id = 0 ) {
169
  static $global_count = 0;
170
 
186
  return $unit_tag;
187
  }
188
 
189
+
190
+ /**
191
+ * Constructor.
192
+ */
193
  private function __construct( $post = null ) {
194
  $post = get_post( $post );
195
 
217
  do_action( 'wpcf7_contact_form', $this );
218
  }
219
 
220
+
221
+ /**
222
+ * Magic method for property overloading.
223
+ */
224
  public function __get( $name ) {
225
  $message = __( '<code>%1$s</code> property of a <code>WPCF7_ContactForm</code> object is <strong>no longer accessible</strong>. Use <code>%2$s</code> method instead.', 'contact-form-7' );
226
 
254
  }
255
  }
256
 
257
+
258
+ /**
259
+ * Returns true if this contact form is not yet saved to the database.
260
+ */
261
  public function initial() {
262
  return empty( $this->id );
263
  }
264
 
265
+
266
+ /**
267
+ * Returns the value for the given property name.
268
+ *
269
+ * @param string $name Property name.
270
+ * @return array|string|null Property value. Null if property doesn't exist.
271
+ */
272
  public function prop( $name ) {
273
  $props = $this->get_properties();
274
  return isset( $props[$name] ) ? $props[$name] : null;
275
  }
276
 
277
+
278
+ /**
279
+ * Returns all the properties.
280
+ *
281
+ * @return array This contact form's properties.
282
+ */
283
  public function get_properties() {
284
  $properties = (array) $this->properties;
285
 
291
  'additional_settings' => '',
292
  ) );
293
 
294
+ $properties = (array) apply_filters(
295
+ 'wpcf7_contact_form_properties',
296
+ $properties, $this
297
+ );
298
 
299
  return $properties;
300
  }
301
 
302
+
303
+ /**
304
+ * Updates properties.
305
+ *
306
+ * @param array $properties New properties.
307
+ */
308
  public function set_properties( $properties ) {
309
  $defaults = $this->get_properties();
310
 
314
  $this->properties = $properties;
315
  }
316
 
317
+
318
+ /**
319
+ * Returns ID of this contact form.
320
+ *
321
+ * @return int The ID.
322
+ */
323
  public function id() {
324
  return $this->id;
325
  }
326
 
327
+
328
+ /**
329
+ * Returns unit-tag for this contact form.
330
+ *
331
+ * @return string Unit-tag.
332
+ */
333
  public function unit_tag() {
334
  return $this->unit_tag;
335
  }
336
 
337
+
338
+ /**
339
+ * Returns name (slug) of this contact form.
340
+ *
341
+ * @return string Name.
342
+ */
343
  public function name() {
344
  return $this->name;
345
  }
346
 
347
+
348
+ /**
349
+ * Returns title of this contact form.
350
+ *
351
+ * @return string Title.
352
+ */
353
  public function title() {
354
  return $this->title;
355
  }
356
 
357
+
358
+ /**
359
+ * Set a title for this contact form.
360
+ *
361
+ * @param string $title Title.
362
+ */
363
  public function set_title( $title ) {
364
  $title = strip_tags( $title );
365
  $title = trim( $title );
371
  $this->title = $title;
372
  }
373
 
374
+
375
+ /**
376
+ * Returns the locale code of this contact form.
377
+ *
378
+ * @return string Locale code. Empty string if no valid locale is set.
379
+ */
380
  public function locale() {
381
  if ( wpcf7_is_valid_locale( $this->locale ) ) {
382
  return $this->locale;
385
  }
386
  }
387
 
388
+
389
+ /**
390
+ * Sets a locale for this contact form.
391
+ *
392
+ * @param string $locale Locale code.
393
+ */
394
  public function set_locale( $locale ) {
395
  $locale = trim( $locale );
396
 
401
  }
402
  }
403
 
404
+
405
+ /**
406
+ * Returns the specified shortcode attribute value.
407
+ *
408
+ * @param string $name Shortcode attribute name.
409
+ * @return string|null Attribute value. Null if the attribute doesn't exist.
410
+ */
411
  public function shortcode_attr( $name ) {
412
  if ( isset( $this->shortcode_atts[$name] ) ) {
413
  return (string) $this->shortcode_atts[$name];
414
  }
415
  }
416
 
417
+
418
+ /**
419
+ * Returns true if this contact form is identical to the submitted one.
420
+ */
421
  public function is_posted() {
422
  if ( ! WPCF7_Submission::get_instance() ) {
423
  return false;
430
  return $this->unit_tag() === $_POST['_wpcf7_unit_tag'];
431
  }
432
 
 
433
 
434
+ /**
435
+ * Generates HTML that represents a form.
436
+ *
437
+ * @param string|array $args Optional. Form options.
438
+ * @return string HTML output.
439
+ */
440
  public function form_html( $args = '' ) {
441
  $args = wp_parse_args( $args, array(
442
  'html_id' => '',
448
  $this->shortcode_atts = $args;
449
 
450
  if ( 'raw_form' == $args['output'] ) {
451
+ return sprintf(
452
+ '<pre class="wpcf7-raw-form"><code>%s</code></pre>',
453
+ esc_html( $this->prop( 'form' ) )
454
+ );
455
  }
456
 
457
  if ( $this->is_true( 'subscribers_only' )
458
  and ! current_user_can( 'wpcf7_submit', $this->id() ) ) {
459
  $notice = __(
460
  "This contact form is available only for logged in users.",
461
+ 'contact-form-7'
462
+ );
463
+
464
  $notice = sprintf(
465
  '<p class="wpcf7-subscribers-only">%s</p>',
466
+ esc_html( $notice )
467
+ );
468
 
469
  return apply_filters( 'wpcf7_subscribers_only_notice', $notice, $this );
470
  }
501
  $url = apply_filters( 'wpcf7_form_action_url', $url );
502
 
503
  $id_attr = apply_filters( 'wpcf7_form_id_attr',
504
+ preg_replace( '/[^A-Za-z0-9:._-]/', '', $args['html_id'] )
505
+ );
506
 
507
  $name_attr = apply_filters( 'wpcf7_form_name_attr',
508
+ preg_replace( '/[^A-Za-z0-9:._-]/', '', $args['html_name'] )
509
+ );
510
 
511
  $class = 'wpcf7-form';
512
 
579
  return $html;
580
  }
581
 
582
+
583
+ /**
584
+ * Returns the class name that matches the given form status.
585
+ */
586
  private function form_status_class_name( $status ) {
587
  switch ( $status ) {
588
  case 'init':
616
  return $class;
617
  }
618
 
619
+
620
+ /**
621
+ * Returns a set of hidden fields.
622
+ */
623
  private function form_hidden_fields() {
624
  $hidden_fields = array(
625
  '_wpcf7' => $this->id(),
634
  $hidden_fields['_wpcf7_container_post'] = (int) get_the_ID();
635
  }
636
 
637
+ if ( $this->nonce_is_active() and is_user_logged_in() ) {
638
  $hidden_fields['_wpnonce'] = wpcf7_create_nonce();
639
  }
640
 
641
  $hidden_fields += (array) apply_filters(
642
+ 'wpcf7_form_hidden_fields', array()
643
+ );
644
 
645
  $content = '';
646
 
647
  foreach ( $hidden_fields as $name => $value ) {
648
  $content .= sprintf(
649
  '<input type="hidden" name="%1$s" value="%2$s" />',
650
+ esc_attr( $name ),
651
+ esc_attr( $value )
652
+ ) . "\n";
653
  }
654
 
655
  return '<div style="display: none;">' . "\n" . $content . '</div>' . "\n";
656
  }
657
 
658
+
659
+ /**
660
+ * Returns the visible response output for a form submission.
661
+ */
662
  public function form_response_output() {
663
  $status = 'init';
664
  $class = 'wpcf7-response-output';
689
  return $output;
690
  }
691
 
692
+
693
+ /**
694
+ * Returns the response output that is only accessible from screen readers.
695
+ */
696
  public function screen_reader_response() {
697
  $primary_response = '';
698
  $validation_errors = array();
749
  return $output;
750
  }
751
 
752
+
753
+ /**
754
+ * Returns a validation error for the specified input field.
755
+ *
756
+ * @param string $name Input field name.
757
+ */
758
  public function validation_error( $name ) {
759
  $error = '';
760
 
784
  return apply_filters( 'wpcf7_validation_error', $error, $name, $this );
785
  }
786
 
 
787
 
788
+ /**
789
+ * Replaces all form-tags in the form template with corresponding HTML.
790
+ *
791
+ * @return string Replaced form content.
792
+ */
793
  public function replace_all_form_tags() {
794
  $manager = WPCF7_FormTagsManager::get_instance();
795
  $form = $this->prop( 'form' );
805
  return $form;
806
  }
807
 
808
+
809
+ /**
810
+ * Replaces all form-tags in the form template with corresponding HTML.
811
+ *
812
+ * @deprecated 4.6 Use replace_all_form_tags()
813
+ *
814
+ * @return string Replaced form content.
815
+ */
816
  public function form_do_shortcode() {
817
  wpcf7_deprecated_function( __METHOD__, '4.6',
818
+ 'WPCF7_ContactForm::replace_all_form_tags'
819
+ );
820
 
821
  return $this->replace_all_form_tags();
822
  }
823
 
824
+
825
+ /**
826
+ * Scans form-tags from the form template.
827
+ *
828
+ * @param string|array|null $cond Optional. Filters. Default null.
829
+ * @return array Form-tags matching the given filter conditions.
830
+ */
831
  public function scan_form_tags( $cond = null ) {
832
  $manager = WPCF7_FormTagsManager::get_instance();
833
 
840
  return $manager->filter( $tags, $cond );
841
  }
842
 
843
+
844
+ /**
845
+ * Scans form-tags from the form template.
846
+ *
847
+ * @deprecated 4.6 Use scan_form_tags()
848
+ *
849
+ * @param string|array|null $cond Optional. Filters. Default null.
850
+ * @return array Form-tags matching the given filter conditions.
851
+ */
852
  public function form_scan_shortcode( $cond = null ) {
853
  wpcf7_deprecated_function( __METHOD__, '4.6',
854
  'WPCF7_ContactForm::scan_form_tags'
857
  return $this->scan_form_tags( $cond );
858
  }
859
 
860
+
861
+ /**
862
+ * Replaces all form-tags in the form template with corresponding HTML.
863
+ *
864
+ * @return string Replaced form content. wpcf7_form_elements filters applied.
865
+ */
866
  public function form_elements() {
867
  return apply_filters( 'wpcf7_form_elements',
868
  $this->replace_all_form_tags()
869
  );
870
  }
871
 
872
+
873
+ /**
874
+ * Collects mail-tags available for this contact form.
875
+ *
876
+ * @param string|array $args Optional. Search options.
877
+ * @return array Mail-tag names.
878
+ */
879
  public function collect_mail_tags( $args = '' ) {
880
  $manager = WPCF7_FormTagsManager::get_instance();
881
 
910
  return apply_filters( 'wpcf7_collect_mail_tags', $mailtags, $args, $this );
911
  }
912
 
913
+
914
+ /**
915
+ * Prints a mail-tag suggestion list.
916
+ *
917
+ * @param string $for Optional. Mail template name. Default 'mail'.
918
+ */
919
  public function suggest_mail_tags( $for = 'mail' ) {
920
  $mail = wp_parse_args( $this->prop( $for ),
921
  array(
949
  }
950
  }
951
 
952
+
953
+ /**
954
+ * Submits this contact form.
955
+ *
956
+ * @param string|array $args Optional. Submission options. Default empty.
957
+ * @return array Result of submission.
958
+ */
959
  public function submit( $args = '' ) {
960
  $args = wp_parse_args( $args, array(
961
  'skip_mail' =>
984
 
985
  $result = array(
986
  'contact_form_id' => $this->id(),
 
 
 
987
  );
988
 
989
+ $result += $submission->get_result();
 
 
990
 
991
+ if ( $this->in_demo_mode() ) {
992
+ $result['demo_mode'] = true;
 
 
 
 
 
 
 
 
993
  }
994
 
995
  do_action( 'wpcf7_submit', $this, $result );
997
  return $result;
998
  }
999
 
 
1000
 
1001
+ /**
1002
+ * Returns message used for given status.
1003
+ *
1004
+ * @param string $status Status.
1005
+ * @param bool $filter Optional. Whether filters are applied. Default true.
1006
+ * @return string Message.
1007
+ */
1008
  public function message( $status, $filter = true ) {
1009
  $messages = $this->prop( 'messages' );
1010
  $message = isset( $messages[$status] ) ? $messages[$status] : '';
1016
  return $message;
1017
  }
1018
 
1019
+
1020
+ /**
1021
+ * Filters a message.
1022
+ *
1023
+ * @param string $message Message to filter.
1024
+ * @param string $status Optional. Status. Default empty.
1025
+ * @return string Filtered message.
1026
+ */
1027
  public function filter_message( $message, $status = '' ) {
1028
  $message = wpcf7_mail_replace_tags( $message );
1029
  $message = apply_filters( 'wpcf7_display_message', $message, $status );
1032
  return $message;
1033
  }
1034
 
 
1035
 
1036
+ /**
1037
+ * Returns the additional setting value searched by name.
1038
+ *
1039
+ * @param string $name Name of setting.
1040
+ * @return string Additional setting value.
1041
+ */
1042
  public function pref( $name ) {
1043
  $settings = $this->additional_setting( $name );
1044
 
1047
  }
1048
  }
1049
 
1050
+
1051
+ /**
1052
+ * Returns additional setting values searched by name.
1053
+ *
1054
+ * @param string $name Name of setting.
1055
+ * @param int $max Maximum result item count.
1056
+ * @return array Additional setting values.
1057
+ */
1058
  public function additional_setting( $name, $max = 1 ) {
1059
  $settings = (array) explode( "\n", $this->prop( 'additional_settings' ) );
1060
 
1078
  return $values;
1079
  }
1080
 
1081
+
1082
+ /**
1083
+ * Returns true if the specified setting has a truthy string value.
1084
+ *
1085
+ * @param string $name Name of setting.
1086
+ * @return bool True if the setting value is 'on', 'true', or '1'.
1087
+ */
1088
  public function is_true( $name ) {
1089
  return in_array(
1090
  $this->pref( $name ),
1093
  );
1094
  }
1095
 
1096
+
1097
+ /**
1098
+ * Returns true if this contact form is in the demo mode.
1099
+ */
1100
  public function in_demo_mode() {
1101
  return $this->is_true( 'demo_mode' );
1102
  }
1103
 
1104
+
1105
+ /**
1106
+ * Returns true if nonce is active for this contact form.
1107
+ */
1108
  public function nonce_is_active() {
1109
  $is_active = WPCF7_VERIFY_NONCE;
1110
 
1115
  return (bool) apply_filters( 'wpcf7_verify_nonce', $is_active, $this );
1116
  }
1117
 
 
1118
 
1119
+ /**
1120
+ * Upgrades this contact form properties.
1121
+ */
1122
  private function upgrade() {
1123
  $mail = $this->prop( 'mail' );
1124
 
1142
  $this->properties['messages'] = $messages;
1143
  }
1144
 
 
1145
 
1146
+ /**
1147
+ * Stores this contact form properties to the database.
1148
+ *
1149
+ * @return int The post ID on success. The value 0 on failure.
1150
+ */
1151
  public function save() {
1152
+ $title = wp_slash( $this->title );
1153
+ $props = wp_slash( $this->get_properties() );
1154
 
1155
  $post_content = implode( "\n", wpcf7_array_flatten( $props ) );
1156
 
1158
  $post_id = wp_insert_post( array(
1159
  'post_type' => self::post_type,
1160
  'post_status' => 'publish',
1161
+ 'post_title' => $title,
1162
  'post_content' => trim( $post_content ),
1163
  ) );
1164
  } else {
1165
  $post_id = wp_update_post( array(
1166
  'ID' => (int) $this->id,
1167
  'post_status' => 'publish',
1168
+ 'post_title' => $title,
1169
  'post_content' => trim( $post_content ),
1170
  ) );
1171
  }
1173
  if ( $post_id ) {
1174
  foreach ( $props as $prop => $value ) {
1175
  update_post_meta( $post_id, '_' . $prop,
1176
+ wpcf7_normalize_newline_deep( $value )
1177
+ );
1178
  }
1179
 
1180
  if ( wpcf7_is_valid_locale( $this->locale ) ) {
1194
  return $post_id;
1195
  }
1196
 
1197
+
1198
+ /**
1199
+ * Makes a copy of this contact form.
1200
+ *
1201
+ * @return WPCF7_ContactForm New contact form object.
1202
+ */
1203
  public function copy() {
1204
  $new = new self;
1205
  $new->title = $this->title . '_copy';
1209
  return apply_filters( 'wpcf7_copy', $new, $this );
1210
  }
1211
 
1212
+
1213
+ /**
1214
+ * Deletes this contact form.
1215
+ */
1216
  public function delete() {
1217
  if ( $this->initial() ) {
1218
  return;
1226
  return false;
1227
  }
1228
 
1229
+
1230
+ /**
1231
+ * Returns a WordPress shortcode for this contact form.
1232
+ */
1233
  public function shortcode( $args = '' ) {
1234
  $args = wp_parse_args( $args, array(
1235
+ 'use_old_format' => false
1236
+ ) );
1237
 
1238
  $title = str_replace( array( '"', '[', ']' ), '', $this->title );
1239
 
1241
  $old_unit_id = (int) get_post_meta( $this->id, '_old_cf7_unit_id', true );
1242
 
1243
  if ( $old_unit_id ) {
1244
+ $shortcode = sprintf(
1245
+ '[contact-form %1$d "%2$s"]',
1246
+ $old_unit_id,
1247
+ $title
1248
+ );
1249
  } else {
1250
  $shortcode = '';
1251
  }
1252
  } else {
1253
+ $shortcode = sprintf(
1254
+ '[contact-form-7 id="%1$d" title="%2$s"]',
1255
+ $this->id,
1256
+ $title
1257
+ );
1258
  }
1259
 
1260
  return apply_filters( 'wpcf7_contact_form_shortcode',
1261
+ $shortcode, $args, $this
1262
+ );
1263
  }
1264
  }
includes/css/styles.css CHANGED
@@ -2,11 +2,13 @@
2
  position: absolute;
3
  overflow: hidden;
4
  clip: rect(1px, 1px, 1px, 1px);
 
5
  height: 1px;
6
  width: 1px;
7
- margin: 0;
8
  padding: 0;
9
  border: 0;
 
10
  }
11
 
12
  .wpcf7 form .wpcf7-response-output {
@@ -35,7 +37,8 @@
35
  }
36
 
37
  .wpcf7 form.invalid .wpcf7-response-output,
38
- .wpcf7 form.unaccepted .wpcf7-response-output {
 
39
  border-color: #ffb900; /* Yellow */
40
  }
41
 
@@ -71,7 +74,7 @@
71
  content: " ";
72
  }
73
 
74
- .wpcf7 .ajax-loader {
75
  visibility: hidden;
76
  display: inline-block;
77
  background-color: #23282d; /* Dark Gray 800 */
@@ -85,11 +88,11 @@
85
  position: relative;
86
  }
87
 
88
- .wpcf7 form.submitting .ajax-loader {
89
  visibility: visible;
90
  }
91
 
92
- .wpcf7 .ajax-loader::before {
93
  content: '';
94
  position: absolute;
95
  background-color: #fbfbfc; /* Light Gray 100 */
@@ -107,7 +110,7 @@
107
  }
108
 
109
  @media (prefers-reduced-motion: reduce) {
110
- .wpcf7 .ajax-loader::before {
111
  animation-name: blink;
112
  animation-duration: 2000ms;
113
  }
2
  position: absolute;
3
  overflow: hidden;
4
  clip: rect(1px, 1px, 1px, 1px);
5
+ clip-path: inset(50%);
6
  height: 1px;
7
  width: 1px;
8
+ margin: -1px;
9
  padding: 0;
10
  border: 0;
11
+ word-wrap: normal !important;
12
  }
13
 
14
  .wpcf7 form .wpcf7-response-output {
37
  }
38
 
39
  .wpcf7 form.invalid .wpcf7-response-output,
40
+ .wpcf7 form.unaccepted .wpcf7-response-output,
41
+ .wpcf7 form.payment-required .wpcf7-response-output {
42
  border-color: #ffb900; /* Yellow */
43
  }
44
 
74
  content: " ";
75
  }
76
 
77
+ .wpcf7-spinner {
78
  visibility: hidden;
79
  display: inline-block;
80
  background-color: #23282d; /* Dark Gray 800 */
88
  position: relative;
89
  }
90
 
91
+ form.submitting .wpcf7-spinner {
92
  visibility: visible;
93
  }
94
 
95
+ .wpcf7-spinner::before {
96
  content: '';
97
  position: absolute;
98
  background-color: #fbfbfc; /* Light Gray 100 */
110
  }
111
 
112
  @media (prefers-reduced-motion: reduce) {
113
+ .wpcf7-spinner::before {
114
  animation-name: blink;
115
  animation-duration: 2000ms;
116
  }
includes/file.php CHANGED
@@ -77,7 +77,7 @@ function wpcf7_unship_uploaded_file( $file, $args = '' ) {
77
  }
78
 
79
  $filename = $name;
80
- $filename = wpcf7_canonicalize( $filename, 'as-is' );
81
  $filename = wpcf7_antiscript_file_name( $filename );
82
 
83
  $filename = apply_filters( 'wpcf7_upload_file_name',
@@ -109,6 +109,10 @@ add_filter(
109
  10, 1
110
  );
111
 
 
 
 
 
112
  function wpcf7_file_messages( $messages ) {
113
  return array_merge( $messages, array(
114
  'upload_failed' => array(
@@ -140,6 +144,10 @@ add_filter(
140
  10, 1
141
  );
142
 
 
 
 
 
143
  function wpcf7_file_form_enctype_filter( $enctype ) {
144
  $multipart = (bool) wpcf7_scan_form_tags( array(
145
  'feature' => 'file-uploading',
@@ -234,9 +242,11 @@ add_action(
234
  10, 0
235
  );
236
 
 
 
 
237
  function wpcf7_init_uploads() {
238
  $dir = wpcf7_upload_tmp_dir();
239
- wp_mkdir_p( $dir );
240
 
241
  if ( is_dir( $dir ) and is_writable( $dir ) ) {
242
  $htaccess_file = path_join( $dir, '.htaccess' );
@@ -250,6 +260,12 @@ function wpcf7_init_uploads() {
250
  }
251
 
252
 
 
 
 
 
 
 
253
  function wpcf7_maybe_add_random_dir( $dir ) {
254
  do {
255
  $rand_max = mt_getrandmax();
@@ -265,12 +281,24 @@ function wpcf7_maybe_add_random_dir( $dir ) {
265
  }
266
 
267
 
 
 
 
 
 
268
  function wpcf7_upload_tmp_dir() {
269
  if ( defined( 'WPCF7_UPLOADS_TMP_DIR' ) ) {
270
- return WPCF7_UPLOADS_TMP_DIR;
271
- } else {
272
- return path_join( wpcf7_upload_dir( 'dir' ), 'wpcf7_uploads' );
 
 
 
273
  }
 
 
 
 
274
  }
275
 
276
 
@@ -280,6 +308,13 @@ add_action(
280
  20, 0
281
  );
282
 
 
 
 
 
 
 
 
283
  function wpcf7_cleanup_upload_files( $seconds = 60, $max = 100 ) {
284
  if ( is_admin()
285
  or 'GET' != $_SERVER['REQUEST_METHOD']
@@ -334,6 +369,9 @@ add_action(
334
  10, 3
335
  );
336
 
 
 
 
337
  function wpcf7_file_display_warning_message( $page, $action, $object ) {
338
  if ( $object instanceof WPCF7_ContactForm ) {
339
  $contact_form = $object;
77
  }
78
 
79
  $filename = $name;
80
+ $filename = wpcf7_canonicalize( $filename, array( 'strto' => 'as-is' ) );
81
  $filename = wpcf7_antiscript_file_name( $filename );
82
 
83
  $filename = apply_filters( 'wpcf7_upload_file_name',
109
  10, 1
110
  );
111
 
112
+ /**
113
+ * A wpcf7_messages filter callback that adds messages for
114
+ * file-uploading fields.
115
+ */
116
  function wpcf7_file_messages( $messages ) {
117
  return array_merge( $messages, array(
118
  'upload_failed' => array(
144
  10, 1
145
  );
146
 
147
+ /**
148
+ * A wpcf7_form_enctype filter callback that sets the enctype attribute
149
+ * to multipart/form-data if the form has file-uploading fields.
150
+ */
151
  function wpcf7_file_form_enctype_filter( $enctype ) {
152
  $multipart = (bool) wpcf7_scan_form_tags( array(
153
  'feature' => 'file-uploading',
242
  10, 0
243
  );
244
 
245
+ /**
246
+ * Initializes the temporary directory for uploaded files.
247
+ */
248
  function wpcf7_init_uploads() {
249
  $dir = wpcf7_upload_tmp_dir();
 
250
 
251
  if ( is_dir( $dir ) and is_writable( $dir ) ) {
252
  $htaccess_file = path_join( $dir, '.htaccess' );
260
  }
261
 
262
 
263
+ /**
264
+ * Creates a child directory with a randomly generated name.
265
+ *
266
+ * @param string $dir The parent directory path.
267
+ * @return string The child directory path if created, otherwise the parent.
268
+ */
269
  function wpcf7_maybe_add_random_dir( $dir ) {
270
  do {
271
  $rand_max = mt_getrandmax();
281
  }
282
 
283
 
284
+ /**
285
+ * Returns the directory path for uploaded files.
286
+ *
287
+ * @return string Directory path.
288
+ */
289
  function wpcf7_upload_tmp_dir() {
290
  if ( defined( 'WPCF7_UPLOADS_TMP_DIR' ) ) {
291
+ $dir = path_join( WP_CONTENT_DIR, WPCF7_UPLOADS_TMP_DIR );
292
+ wp_mkdir_p( $dir );
293
+
294
+ if ( wpcf7_is_file_path_in_content_dir( $dir ) ) {
295
+ return $dir;
296
+ }
297
  }
298
+
299
+ $dir = path_join( wpcf7_upload_dir( 'dir' ), 'wpcf7_uploads' );
300
+ wp_mkdir_p( $dir );
301
+ return $dir;
302
  }
303
 
304
 
308
  20, 0
309
  );
310
 
311
+ /**
312
+ * Cleans up files in the temporary directory for uploaded files.
313
+ *
314
+ * @param int $seconds Files older than this are removed. Default 60.
315
+ * @param int $max Maximum number of files to be removed in a function call.
316
+ * Default 100.
317
+ */
318
  function wpcf7_cleanup_upload_files( $seconds = 60, $max = 100 ) {
319
  if ( is_admin()
320
  or 'GET' != $_SERVER['REQUEST_METHOD']
369
  10, 3
370
  );
371
 
372
+ /**
373
+ * Displays warning messages about file-uploading fields.
374
+ */
375
  function wpcf7_file_display_warning_message( $page, $action, $object ) {
376
  if ( $object instanceof WPCF7_ContactForm ) {
377
  $contact_form = $object;
includes/form-tag.php CHANGED
@@ -4,6 +4,7 @@ class WPCF7_FormTag implements ArrayAccess {
4
 
5
  public $type;
6
  public $basetype;
 
7
  public $name = '';
8
  public $options = array();
9
  public $raw_values = array();
4
 
5
  public $type;
6
  public $basetype;
7
+ public $raw_name = '';
8
  public $name = '';
9
  public $options = array();
10
  public $raw_values = array();
includes/form-tags-manager.php CHANGED
@@ -90,7 +90,8 @@ class WPCF7_FormTagsManager {
90
  if ( isset( $this->tag_types[$tag]['features'] ) ) {
91
  return (bool) array_intersect(
92
  array_keys( array_filter( $this->tag_types[$tag]['features'] ) ),
93
- $feature );
 
94
  }
95
 
96
  return false;
@@ -183,14 +184,16 @@ class WPCF7_FormTagsManager {
183
  $content = preg_replace_callback(
184
  '/' . $this->tag_regex() . '/s',
185
  array( $this, 'replace_callback' ),
186
- $content );
 
187
 
188
  return $content;
189
  } else {
190
  preg_replace_callback(
191
  '/' . $this->tag_regex() . '/s',
192
  array( $this, 'scan_callback' ),
193
- $content );
 
194
 
195
  return $this->scanned_tags;
196
  }
@@ -282,6 +285,7 @@ class WPCF7_FormTagsManager {
282
  $scanned_tag = array(
283
  'type' => $tag,
284
  'basetype' => trim( $tag, '*' ),
 
285
  'name' => '',
286
  'options' => array(),
287
  'raw_values' => array(),
@@ -292,15 +296,23 @@ class WPCF7_FormTagsManager {
292
  'content' => '',
293
  );
294
 
 
 
 
 
 
 
295
  if ( is_array( $attr ) ) {
296
  if ( is_array( $attr['options'] ) ) {
297
  if ( $this->tag_type_supports( $tag, 'name-attr' )
298
  and ! empty( $attr['options'] ) ) {
299
- $scanned_tag['name'] = array_shift( $attr['options'] );
300
 
301
- if ( ! wpcf7_is_name( $scanned_tag['name'] ) ) {
302
  return $m[0]; // Invalid name is used. Ignore this tag.
303
  }
 
 
304
  }
305
 
306
  $scanned_tag['options'] = (array) $attr['options'];
@@ -346,7 +358,7 @@ class WPCF7_FormTagsManager {
346
  private function parse_atts( $text ) {
347
  $atts = array( 'options' => array(), 'values' => array() );
348
  $text = preg_replace( "/[\x{00a0}\x{200b}]+/u", " ", $text );
349
- $text = stripcslashes( trim( $text ) );
350
 
351
  $pattern = '%^([-+*=0-9a-zA-Z:.!?#$&@_/|\%\r\n\t ]*?)((?:[\r\n\t ]*"[^"]*"|[\r\n\t ]*\'[^\']*\')*)$%';
352
 
90
  if ( isset( $this->tag_types[$tag]['features'] ) ) {
91
  return (bool) array_intersect(
92
  array_keys( array_filter( $this->tag_types[$tag]['features'] ) ),
93
+ $feature
94
+ );
95
  }
96
 
97
  return false;
184
  $content = preg_replace_callback(
185
  '/' . $this->tag_regex() . '/s',
186
  array( $this, 'replace_callback' ),
187
+ $content
188
+ );
189
 
190
  return $content;
191
  } else {
192
  preg_replace_callback(
193
  '/' . $this->tag_regex() . '/s',
194
  array( $this, 'scan_callback' ),
195
+ $content
196
+ );
197
 
198
  return $this->scanned_tags;
199
  }
285
  $scanned_tag = array(
286
  'type' => $tag,
287
  'basetype' => trim( $tag, '*' ),
288
+ 'raw_name' => '',
289
  'name' => '',
290
  'options' => array(),
291
  'raw_values' => array(),
296
  'content' => '',
297
  );
298
 
299
+ if ( $this->tag_type_supports( $tag, 'singular' )
300
+ and $this->filter( $this->scanned_tags, array( 'type' => $tag ) ) ) {
301
+ // Another tag in the same type already exists. Ignore this one.
302
+ return $m[0];
303
+ }
304
+
305
  if ( is_array( $attr ) ) {
306
  if ( is_array( $attr['options'] ) ) {
307
  if ( $this->tag_type_supports( $tag, 'name-attr' )
308
  and ! empty( $attr['options'] ) ) {
309
+ $scanned_tag['raw_name'] = array_shift( $attr['options'] );
310
 
311
+ if ( ! wpcf7_is_name( $scanned_tag['raw_name'] ) ) {
312
  return $m[0]; // Invalid name is used. Ignore this tag.
313
  }
314
+
315
+ $scanned_tag['name'] = strtr( $scanned_tag['raw_name'], '.', '_' );
316
  }
317
 
318
  $scanned_tag['options'] = (array) $attr['options'];
358
  private function parse_atts( $text ) {
359
  $atts = array( 'options' => array(), 'values' => array() );
360
  $text = preg_replace( "/[\x{00a0}\x{200b}]+/u", " ", $text );
361
+ $text = trim( $text );
362
 
363
  $pattern = '%^([-+*=0-9a-zA-Z:.!?#$&@_/|\%\r\n\t ]*?)((?:[\r\n\t ]*"[^"]*"|[\r\n\t ]*\'[^\']*\')*)$%';
364
 
includes/formatting.php CHANGED
@@ -1,5 +1,16 @@
1
  <?php
2
 
 
 
 
 
 
 
 
 
 
 
 
3
  function wpcf7_autop( $pee, $br = 1 ) {
4
  if ( trim( $pee ) === '' ) {
5
  return '';
@@ -77,15 +88,30 @@ function wpcf7_autop( $pee, $br = 1 ) {
77
  'clean_pre', $pee );
78
  }
79
 
 
80
  $pee = preg_replace( "|\n</p>$|", '</p>', $pee );
81
 
82
  return $pee;
83
  }
84
 
 
 
 
 
 
 
 
85
  function wpcf7_autop_preserve_newline_callback( $matches ) {
86
  return str_replace( "\n", '<WPPreserveNewline />', $matches[0] );
87
  }
88
 
 
 
 
 
 
 
 
89
  function wpcf7_sanitize_query_var( $text ) {
90
  $text = wp_unslash( $text );
91
  $text = wp_check_invalid_utf8( $text );
@@ -102,6 +128,13 @@ function wpcf7_sanitize_query_var( $text ) {
102
  return $text;
103
  }
104
 
 
 
 
 
 
 
 
105
  function wpcf7_strip_quote( $text ) {
106
  $text = trim( $text );
107
 
@@ -114,6 +147,14 @@ function wpcf7_strip_quote( $text ) {
114
  return $text;
115
  }
116
 
 
 
 
 
 
 
 
 
117
  function wpcf7_strip_quote_deep( $arr ) {
118
  if ( is_string( $arr ) ) {
119
  return wpcf7_strip_quote( $arr );
@@ -130,6 +171,14 @@ function wpcf7_strip_quote_deep( $arr ) {
130
  }
131
  }
132
 
 
 
 
 
 
 
 
 
133
  function wpcf7_normalize_newline( $text, $to = "\n" ) {
134
  if ( ! is_string( $text ) ) {
135
  return $text;
@@ -144,6 +193,15 @@ function wpcf7_normalize_newline( $text, $to = "\n" ) {
144
  return str_replace( $nls, $to, $text );
145
  }
146
 
 
 
 
 
 
 
 
 
 
147
  function wpcf7_normalize_newline_deep( $arr, $to = "\n" ) {
148
  if ( is_array( $arr ) ) {
149
  $result = array();
@@ -158,33 +216,105 @@ function wpcf7_normalize_newline_deep( $arr, $to = "\n" ) {
158
  return wpcf7_normalize_newline( $arr, $to );
159
  }
160
 
 
 
 
 
 
 
 
161
  function wpcf7_strip_newline( $str ) {
162
  $str = (string) $str;
163
  $str = str_replace( array( "\r", "\n" ), '', $str );
164
  return trim( $str );
165
  }
166
 
167
- function wpcf7_canonicalize( $text, $strto = 'lower' ) {
168
- if ( function_exists( 'mb_convert_kana' )
169
- and 'UTF-8' == get_option( 'blog_charset' ) ) {
170
- $text = mb_convert_kana( $text, 'asKV', 'UTF-8' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
171
  }
172
 
173
- if ( 'lower' == $strto ) {
174
- $text = strtolower( $text );
175
- } elseif ( 'upper' == $strto ) {
176
- $text = strtoupper( $text );
 
 
 
 
 
 
 
 
177
  }
178
 
179
  $text = trim( $text );
180
  return $text;
181
  }
182
 
 
 
 
 
 
 
 
183
  function wpcf7_sanitize_unit_tag( $tag ) {
184
  $tag = preg_replace( '/[^A-Za-z0-9_-]/', '', $tag );
185
  return $tag;
186
  }
187
 
 
 
 
 
 
 
 
188
  function wpcf7_antiscript_file_name( $filename ) {
189
  $filename = wp_basename( $filename );
190
 
@@ -252,3 +382,167 @@ function wpcf7_mask_password( $text, $right = 0, $left = 0 ) {
252
 
253
  return $text;
254
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <?php
2
 
3
+ /**
4
+ * Replaces double line breaks with paragraph elements.
5
+ *
6
+ * This is a variant of wpautop() that is specifically tuned for
7
+ * form content uses.
8
+ *
9
+ * @param string $pee The text which has to be formatted.
10
+ * @param bool $br Optional. If set, this will convert all remaining
11
+ * line breaks after paragraphing. Default true.
12
+ * @return string Text which has been converted into correct paragraph tags.
13
+ */
14
  function wpcf7_autop( $pee, $br = 1 ) {
15
  if ( trim( $pee ) === '' ) {
16
  return '';
88
  'clean_pre', $pee );
89
  }
90
 
91
+ $pee = preg_replace( "|<br />$|", '', $pee );
92
  $pee = preg_replace( "|\n</p>$|", '</p>', $pee );
93
 
94
  return $pee;
95
  }
96
 
97
+
98
+ /**
99
+ * Newline preservation help function for wpcf7_autop().
100
+ *
101
+ * @param array $matches preg_replace_callback() matches array.
102
+ * @return string Text including newline placeholders.
103
+ */
104
  function wpcf7_autop_preserve_newline_callback( $matches ) {
105
  return str_replace( "\n", '<WPPreserveNewline />', $matches[0] );
106
  }
107
 
108
+
109
+ /**
110
+ * Sanitizes the query variables.
111
+ *
112
+ * @param string $text Query variable.
113
+ * @return string Text sanitized.
114
+ */
115
  function wpcf7_sanitize_query_var( $text ) {
116
  $text = wp_unslash( $text );
117
  $text = wp_check_invalid_utf8( $text );
128
  return $text;
129
  }
130
 
131
+
132
+ /**
133
+ * Strips quote characters surrounding the input.
134
+ *
135
+ * @param string $text Input text.
136
+ * @return string Processed output.
137
+ */
138
  function wpcf7_strip_quote( $text ) {
139
  $text = trim( $text );
140
 
147
  return $text;
148
  }
149
 
150
+
151
+ /**
152
+ * Navigates through an array, object, or scalar, and
153
+ * strips quote characters surrounding the each value.
154
+ *
155
+ * @param mixed $arr The array or string to be processed.
156
+ * @return mixed Processed value.
157
+ */
158
  function wpcf7_strip_quote_deep( $arr ) {
159
  if ( is_string( $arr ) ) {
160
  return wpcf7_strip_quote( $arr );
171
  }
172
  }
173
 
174
+
175
+ /**
176
+ * Normalizes newline characters.
177
+ *
178
+ * @param string $text Input text.
179
+ * @param string $to Optional. The newline character that is used in the output.
180
+ * @return string Normalized text.
181
+ */
182
  function wpcf7_normalize_newline( $text, $to = "\n" ) {
183
  if ( ! is_string( $text ) ) {
184
  return $text;
193
  return str_replace( $nls, $to, $text );
194
  }
195
 
196
+
197
+ /**
198
+ * Navigates through an array, object, or scalar, and
199
+ * normalizes newline characters in the each value.
200
+ *
201
+ * @param mixed $arr The array or string to be processed.
202
+ * @param string $to Optional. The newline character that is used in the output.
203
+ * @return mixed Processed value.
204
+ */
205
  function wpcf7_normalize_newline_deep( $arr, $to = "\n" ) {
206
  if ( is_array( $arr ) ) {
207
  $result = array();
216
  return wpcf7_normalize_newline( $arr, $to );
217
  }
218
 
219
+
220
+ /**
221
+ * Strips newline characters.
222
+ *
223
+ * @param string $str Input text.
224
+ * @return string Processed one-line text.
225
+ */
226
  function wpcf7_strip_newline( $str ) {
227
  $str = (string) $str;
228
  $str = str_replace( array( "\r", "\n" ), '', $str );
229
  return trim( $str );
230
  }
231
 
232
+
233
+ /**
234
+ * Canonicalizes text.
235
+ *
236
+ * @param string $text Input text.
237
+ * @param string|array|object $args Options.
238
+ * @return string Canonicalized text.
239
+ */
240
+ function wpcf7_canonicalize( $text, $args = '' ) {
241
+ // for back-compat
242
+ if ( is_string( $args ) and '' !== $args
243
+ and false === strpos( $args, '=' ) ) {
244
+ $args = array(
245
+ 'strto' => $args,
246
+ );
247
+ }
248
+
249
+ $args = wp_parse_args( $args, array(
250
+ 'strto' => 'lower',
251
+ 'strip_separators' => false,
252
+ ) );
253
+
254
+ static $charset = null;
255
+
256
+ if ( ! isset( $charset ) ) {
257
+ $charset = get_option( 'blog_charset' );
258
+
259
+ $is_utf8 = in_array(
260
+ $charset,
261
+ array( 'utf8', 'utf-8', 'UTF8', 'UTF-8' )
262
+ );
263
+
264
+ if ( $is_utf8 ) {
265
+ $charset = 'UTF-8';
266
+ }
267
+ }
268
+
269
+ $text = html_entity_decode( $text, ENT_QUOTES | ENT_HTML5, $charset );
270
+
271
+ if ( function_exists( 'mb_convert_kana' ) ) {
272
+ $text = mb_convert_kana( $text, 'asKV', $charset );
273
+ }
274
+
275
+ if ( $args['strip_separators'] ) {
276
+ $text = preg_replace( '/[\r\n\t ]+/', '', $text );
277
+ } else {
278
+ $text = preg_replace( '/[\r\n\t ]+/', ' ', $text );
279
  }
280
 
281
+ if ( 'lower' == $args['strto'] ) {
282
+ if ( function_exists( 'mb_strtolower' ) ) {
283
+ $text = mb_strtolower( $text, $charset );
284
+ } else {
285
+ $text = strtolower( $text );
286
+ }
287
+ } elseif ( 'upper' == $args['strto'] ) {
288
+ if ( function_exists( 'mb_strtoupper' ) ) {
289
+ $text = mb_strtoupper( $text, $charset );
290
+ } else {
291
+ $text = strtoupper( $text );
292
+ }
293
  }
294
 
295
  $text = trim( $text );
296
  return $text;
297
  }
298
 
299
+
300
+ /**
301
+ * Sanitizes Contact Form 7's form unit-tag.
302
+ *
303
+ * @param string $tag Unit-tag.
304
+ * @return string Sanitized unit-tag.
305
+ */
306
  function wpcf7_sanitize_unit_tag( $tag ) {
307
  $tag = preg_replace( '/[^A-Za-z0-9_-]/', '', $tag );
308
  return $tag;
309
  }
310
 
311
+
312
+ /**
313
+ * Converts a file name to one that is not executable as a script.
314
+ *
315
+ * @param string $filename File name.
316
+ * @return string Converted file name.
317
+ */
318
  function wpcf7_antiscript_file_name( $filename ) {
319
  $filename = wp_basename( $filename );
320
 
382
 
383
  return $text;
384
  }
385
+
386
+
387
+ /**
388
+ * Returns an array of allowed HTML tags and attributes for a given context.
389
+ *
390
+ * @param string $context Context used to decide allowed tags and attributes.
391
+ * @return array Array of allowed HTML tags and their allowed attributes.
392
+ */
393
+ function wpcf7_kses_allowed_html( $context = 'form' ) {
394
+ static $allowed_tags = array();
395
+
396
+ if ( isset( $allowed_tags[$context] ) ) {
397
+ return apply_filters(
398
+ 'wpcf7_kses_allowed_html',
399
+ $allowed_tags[$context],
400
+ $context
401
+ );
402
+ }
403
+
404
+ $allowed_tags[$context] = wp_kses_allowed_html( 'post' );
405
+
406
+ if ( 'form' === $context ) {
407
+ $additional_tags_for_form = array(
408
+ 'button' => array(
409
+ 'disabled' => true,
410
+ 'name' => true,
411
+ 'type' => true,
412
+ 'value' => true,
413
+ ),
414
+ 'datalist' => array(),
415
+ 'fieldset' => array(
416
+ 'disabled' => true,
417
+ 'name' => true,
418
+ ),
419
+ 'input' => array(
420
+ 'accept' => true,
421
+ 'alt' => true,
422
+ 'capture' => true,
423
+ 'checked' => true,
424
+ 'disabled' => true,
425
+ 'list' => true,
426
+ 'max' => true,
427
+ 'maxlength' => true,
428
+ 'min' => true,
429
+ 'minlength' => true,
430
+ 'multiple' => true,
431
+ 'name' => true,
432
+ 'placeholder' => true,
433
+ 'readonly' => true,
434
+ 'size' => true,
435
+ 'step' => true,
436
+ 'type' => true,
437
+ 'value' => true,
438
+ ),
439
+ 'label' => array(
440
+ 'for' => true,
441
+ ),
442
+ 'legend' => array(),
443
+ 'meter' => array(
444
+ 'value' => true,
445
+ 'min' => true,
446
+ 'max' => true,
447
+ 'low' => true,
448
+ 'high' => true,
449
+ 'optimum' => true,
450
+ ),
451
+ 'optgroup' => array(
452
+ 'disabled' => true,
453
+ 'label' => true,
454
+ ),
455
+ 'option' => array(
456
+ 'disabled' => true,
457
+ 'label' => true,
458
+ 'selected' => true,
459
+ 'value' => true,
460
+ ),
461
+ 'output' => array(
462
+ 'for' => true,
463
+ 'name' => true,
464
+ ),
465
+ 'progress' => array(
466
+ 'max' => true,
467
+ 'value' => true,
468
+ ),
469
+ 'select' => array(
470
+ 'disabled' => true,
471
+ 'multiple' => true,
472
+ 'name' => true,
473
+ 'size' => true,
474
+ ),
475
+ 'textarea' => array(
476
+ 'cols' => true,
477
+ 'disabled' => true,
478
+ 'maxlength' => true,
479
+ 'minlength' => true,
480
+ 'name' => true,
481
+ 'placeholder' => true,
482
+ 'readonly' => true,
483
+ 'rows' => true,
484
+ 'spellcheck' => true,
485
+ 'wrap' => true,
486
+ ),
487
+ );
488
+
489
+ $additional_tags_for_form = array_map(
490
+ function ( $elm ) {
491
+ $global_attributes = array(
492
+ 'aria-atomic' => true,
493
+ 'aria-checked' => true,
494
+ 'aria-describedby' => true,
495
+ 'aria-details' => true,
496
+ 'aria-disabled' => true,
497
+ 'aria-hidden' => true,
498
+ 'aria-invalid' => true,
499
+ 'aria-label' => true,
500
+ 'aria-labelledby' => true,
501
+ 'aria-live' => true,
502
+ 'aria-relevant' => true,
503
+ 'aria-required' => true,
504
+ 'aria-selected' => true,
505
+ 'class' => true,
506
+ 'data-*' => true,
507
+ 'id' => true,
508
+ 'inputmode' => true,
509
+ 'role' => true,
510
+ 'style' => true,
511
+ 'tabindex' => true,
512
+ 'title' => true,
513
+ );
514
+
515
+ return array_merge( $global_attributes, (array) $elm );
516
+ },
517
+ $additional_tags_for_form
518
+ );
519
+
520
+ $allowed_tags[$context] = array_merge(
521
+ $allowed_tags[$context],
522
+ $additional_tags_for_form
523
+ );
524
+ }
525
+
526
+ return apply_filters(
527
+ 'wpcf7_kses_allowed_html',
528
+ $allowed_tags[$context],
529
+ $context
530
+ );
531
+ }
532
+
533
+
534
+ /**
535
+ * Sanitizes content for allowed HTML tags for the specified context.
536
+ *
537
+ * @param string $input Content to filter.
538
+ * @param string $context Context used to decide allowed tags and attributes.
539
+ * @return string Filtered text with allowed HTML tags and attributes intact.
540
+ */
541
+ function wpcf7_kses( $input, $context = 'form' ) {
542
+ $output = wp_kses(
543
+ $input,
544
+ wpcf7_kses_allowed_html( $context )
545
+ );
546
+
547
+ return $output;
548
+ }
includes/functions.php CHANGED
@@ -1,9 +1,22 @@
1
  <?php
2
 
 
 
 
 
 
 
3
  function wpcf7_plugin_path( $path = '' ) {
4
  return path_join( WPCF7_PLUGIN_DIR, trim( $path, '/' ) );
5
  }
6
 
 
 
 
 
 
 
 
7
  function wpcf7_plugin_url( $path = '' ) {
8
  $url = plugins_url( $path, WPCF7_PLUGIN );
9
 
@@ -15,6 +28,13 @@ function wpcf7_plugin_url( $path = '' ) {
15
  return $url;
16
  }
17
 
 
 
 
 
 
 
 
18
  function wpcf7_upload_dir( $type = false ) {
19
  $uploads = wp_get_upload_dir();
20
 
@@ -32,14 +52,41 @@ function wpcf7_upload_dir( $type = false ) {
32
  return $uploads;
33
  }
34
 
 
 
 
 
 
 
 
 
 
 
 
35
  function wpcf7_verify_nonce( $nonce, $action = 'wp_rest' ) {
36
  return wp_verify_nonce( $nonce, $action );
37
  }
38
 
 
 
 
 
 
 
 
 
 
39
  function wpcf7_create_nonce( $action = 'wp_rest' ) {
40
  return wp_create_nonce( $action );
41
  }
42
 
 
 
 
 
 
 
 
43
  function wpcf7_array_flatten( $input ) {
44
  if ( ! is_array( $input ) ) {
45
  return array( $input );
@@ -54,47 +101,93 @@ function wpcf7_array_flatten( $input ) {
54
  return $output;
55
  }
56
 
 
 
 
 
 
 
 
57
  function wpcf7_flat_join( $input ) {
58
  $input = wpcf7_array_flatten( $input );
59
  $output = array();
60
 
61
  foreach ( (array) $input as $value ) {
62
- $output[] = trim( (string) $value );
 
 
63
  }
64
 
65
  return implode( ', ', $output );
66
  }
67
 
 
 
 
 
68
  function wpcf7_support_html5() {
69
  return (bool) apply_filters( 'wpcf7_support_html5', true );
70
  }
71
 
 
 
 
 
72
  function wpcf7_support_html5_fallback() {
73
  return (bool) apply_filters( 'wpcf7_support_html5_fallback', false );
74
  }
75
 
 
 
 
 
76
  function wpcf7_use_really_simple_captcha() {
77
  return apply_filters( 'wpcf7_use_really_simple_captcha',
78
- WPCF7_USE_REALLY_SIMPLE_CAPTCHA );
 
79
  }
80
 
 
 
 
 
81
  function wpcf7_validate_configuration() {
82
  return apply_filters( 'wpcf7_validate_configuration',
83
- WPCF7_VALIDATE_CONFIGURATION );
 
84
  }
85
 
 
 
 
 
86
  function wpcf7_autop_or_not() {
87
  return (bool) apply_filters( 'wpcf7_autop_or_not', WPCF7_AUTOP );
88
  }
89
 
 
 
 
 
90
  function wpcf7_load_js() {
91
  return apply_filters( 'wpcf7_load_js', WPCF7_LOAD_JS );
92
  }
93
 
 
 
 
 
94
  function wpcf7_load_css() {
95
  return apply_filters( 'wpcf7_load_css', WPCF7_LOAD_CSS );
96
  }
97
 
 
 
 
 
 
 
 
98
  function wpcf7_format_atts( $atts ) {
99
  $html = '';
100
 
@@ -127,6 +220,15 @@ function wpcf7_format_atts( $atts ) {
127
  return $html;
128
  }
129
 
 
 
 
 
 
 
 
 
 
130
  function wpcf7_link( $url, $anchor_text, $args = '' ) {
131
  $defaults = array(
132
  'id' => '',
@@ -140,11 +242,16 @@ function wpcf7_link( $url, $anchor_text, $args = '' ) {
140
  $link = sprintf( '<a href="%1$s"%3$s>%2$s</a>',
141
  esc_url( $url ),
142
  esc_html( $anchor_text ),
143
- $atts ? ( ' ' . $atts ) : '' );
 
144
 
145
  return $link;
146
  }
147
 
 
 
 
 
148
  function wpcf7_get_request_uri() {
149
  static $request_uri = '';
150
 
@@ -155,6 +262,10 @@ function wpcf7_get_request_uri() {
155
  return esc_url_raw( $request_uri );
156
  }
157
 
 
 
 
 
158
  function wpcf7_register_post_types() {
159
  if ( class_exists( 'WPCF7_ContactForm' ) ) {
160
  WPCF7_ContactForm::register_post_type();
@@ -164,6 +275,13 @@ function wpcf7_register_post_types() {
164
  }
165
  }
166
 
 
 
 
 
 
 
 
167
  function wpcf7_version( $args = '' ) {
168
  $defaults = array(
169
  'limit' => -1,
@@ -194,12 +312,27 @@ function wpcf7_version( $args = '' ) {
194
  return $ver;
195
  }
196
 
 
 
 
 
 
 
 
 
197
  function wpcf7_version_grep( $version, array $input ) {
198
  $pattern = '/^' . preg_quote( (string) $version, '/' ) . '(?:\.|$)/';
199
 
200
  return preg_grep( $pattern, $input );
201
  }
202
 
 
 
 
 
 
 
 
203
  function wpcf7_enctype_value( $enctype ) {
204
  $enctype = trim( $enctype );
205
 
@@ -226,6 +359,13 @@ function wpcf7_enctype_value( $enctype ) {
226
  return '';
227
  }
228
 
 
 
 
 
 
 
 
229
  function wpcf7_rmdir_p( $dir ) {
230
  if ( is_file( $dir ) ) {
231
  $file = $dir;
@@ -272,7 +412,16 @@ function wpcf7_rmdir_p( $dir ) {
272
  return false;
273
  }
274
 
275
- /* From _http_build_query in wp-includes/functions.php */
 
 
 
 
 
 
 
 
 
276
  function wpcf7_build_query( $args, $key = '' ) {
277
  $sep = '&';
278
  $ret = array();
@@ -300,12 +449,15 @@ function wpcf7_build_query( $args, $key = '' ) {
300
  return implode( $sep, $ret );
301
  }
302
 
 
303
  /**
304
  * Returns the number of code units in a string.
305
  *
306
  * @see http://www.w3.org/TR/html5/infrastructure.html#code-unit-length
307
  *
308
- * @return int|bool The number of code units, or false if mb_convert_encoding is not available.
 
 
309
  */
310
  function wpcf7_count_code_units( $string ) {
311
  static $use_mb = null;
@@ -334,11 +486,24 @@ function wpcf7_count_code_units( $string ) {
334
  return floor( $byte_count / 2 );
335
  }
336
 
 
 
 
 
337
  function wpcf7_is_localhost() {
338
  $server_name = strtolower( $_SERVER['SERVER_NAME'] );
339
  return in_array( $server_name, array( 'localhost', '127.0.0.1' ) );
340
  }
341
 
 
 
 
 
 
 
 
 
 
342
  function wpcf7_deprecated_function( $function, $version, $replacement ) {
343
  if ( WP_DEBUG ) {
344
  if ( function_exists( '__' ) ) {
@@ -362,6 +527,17 @@ function wpcf7_deprecated_function( $function, $version, $replacement ) {
362
  }
363
  }
364
 
 
 
 
 
 
 
 
 
 
 
 
365
  function wpcf7_apply_filters_deprecated( $tag, $args, $version, $replacement ) {
366
  if ( ! has_filter( $tag ) ) {
367
  return $args[0];
@@ -381,6 +557,15 @@ function wpcf7_apply_filters_deprecated( $tag, $args, $version, $replacement ) {
381
  return apply_filters_ref_array( $tag, $args );
382
  }
383
 
 
 
 
 
 
 
 
 
 
384
  function wpcf7_doing_it_wrong( $function, $message, $version ) {
385
  if ( WP_DEBUG ) {
386
  if ( function_exists( '__' ) ) {
@@ -423,6 +608,14 @@ function wpcf7_doing_it_wrong( $function, $message, $version ) {
423
  }
424
  }
425
 
 
 
 
 
 
 
 
 
426
  function wpcf7_log_remote_request( $url, $request, $response ) {
427
  $log = sprintf(
428
  /* translators: 1: response code, 2: message, 3: body, 4: URL */
@@ -442,6 +635,13 @@ function wpcf7_log_remote_request( $url, $request, $response ) {
442
  }
443
  }
444
 
 
 
 
 
 
 
 
445
  function wpcf7_anonymize_ip_addr( $ip_addr ) {
446
  if ( ! function_exists( 'inet_ntop' )
447
  or ! function_exists( 'inet_pton' ) ) {
1
  <?php
2
 
3
+ /**
4
+ * Returns path to a plugin file.
5
+ *
6
+ * @param string $path File path relative to the plugin root directory.
7
+ * @return string Absolute file path.
8
+ */
9
  function wpcf7_plugin_path( $path = '' ) {
10
  return path_join( WPCF7_PLUGIN_DIR, trim( $path, '/' ) );
11
  }
12
 
13
+
14
+ /**
15
+ * Returns the URL to a plugin file.
16
+ *
17
+ * @param string $path File path relative to the plugin root directory.
18
+ * @return string URL.
19
+ */
20
  function wpcf7_plugin_url( $path = '' ) {
21
  $url = plugins_url( $path, WPCF7_PLUGIN );
22
 
28
  return $url;
29
  }
30
 
31
+
32
+ /**
33
+ * Retrieves uploads directory information.
34
+ *
35
+ * @param string|bool $type Optional. Type of output. Default false.
36
+ * @return array|string Information about the upload directory.
37
+ */
38
  function wpcf7_upload_dir( $type = false ) {
39
  $uploads = wp_get_upload_dir();
40
 
52
  return $uploads;
53
  }
54
 
55
+
56
+ /**
57
+ * Verifies that a correct security nonce was used with time limit.
58
+ *
59
+ * @param string $nonce Nonce value that was used for verification.
60
+ * @param string $action Optional. Context to what is taking place.
61
+ * Default 'wp_rest'.
62
+ * @return int|bool 1 if the nonce is generated between 0-12 hours ago,
63
+ * 2 if the nonce is generated between 12-24 hours ago.
64
+ * False if the nonce is invalid.
65
+ */
66
  function wpcf7_verify_nonce( $nonce, $action = 'wp_rest' ) {
67
  return wp_verify_nonce( $nonce, $action );
68
  }
69
 
70
+
71
+ /**
72
+ * Creates a cryptographic token tied to a specific action, user, user session,
73
+ * and window of time.
74
+ *
75
+ * @param string $action Optional. Context to what is taking place.
76
+ * Default 'wp_rest'.
77
+ * @return string The token.
78
+ */
79
  function wpcf7_create_nonce( $action = 'wp_rest' ) {
80
  return wp_create_nonce( $action );
81
  }
82
 
83
+
84
+ /**
85
+ * Converts multi-dimensional array to a flat array.
86
+ *
87
+ * @param mixed $input Array or item of array.
88
+ * @return array Flatten array.
89
+ */
90
  function wpcf7_array_flatten( $input ) {
91
  if ( ! is_array( $input ) ) {
92
  return array( $input );
101
  return $output;
102
  }
103
 
104
+
105
+ /**
106
+ * Creates a comma-separated list from a multi-dimensional array.
107
+ *
108
+ * @param mixed $input Array or item of array.
109
+ * @return string Comma-separated list.
110
+ */
111
  function wpcf7_flat_join( $input ) {
112
  $input = wpcf7_array_flatten( $input );
113
  $output = array();
114
 
115
  foreach ( (array) $input as $value ) {
116
+ if ( is_scalar( $value ) ) {
117
+ $output[] = trim( (string) $value );
118
+ }
119
  }
120
 
121
  return implode( ', ', $output );
122
  }
123
 
124
+
125
+ /**
126
+ * Returns true if HTML5 is supported.
127
+ */
128
  function wpcf7_support_html5() {
129
  return (bool) apply_filters( 'wpcf7_support_html5', true );
130
  }
131
 
132
+
133
+ /**
134
+ * Returns true if HTML5 fallback is active.
135
+ */
136
  function wpcf7_support_html5_fallback() {
137
  return (bool) apply_filters( 'wpcf7_support_html5_fallback', false );
138
  }
139
 
140
+
141
+ /**
142
+ * Returns true if the Really Simple CAPTCHA plugin is used for contact forms.
143
+ */
144
  function wpcf7_use_really_simple_captcha() {
145
  return apply_filters( 'wpcf7_use_really_simple_captcha',
146
+ WPCF7_USE_REALLY_SIMPLE_CAPTCHA
147
+ );
148
  }
149
 
150
+
151
+ /**
152
+ * Returns true if config validation is active.
153
+ */
154
  function wpcf7_validate_configuration() {
155
  return apply_filters( 'wpcf7_validate_configuration',
156
+ WPCF7_VALIDATE_CONFIGURATION
157
+ );
158
  }
159
 
160
+
161
+ /**
162
+ * Returns true if wpcf7_autop() is applied to form content.
163
+ */
164
  function wpcf7_autop_or_not() {
165
  return (bool) apply_filters( 'wpcf7_autop_or_not', WPCF7_AUTOP );
166
  }
167
 
168
+
169
+ /**
170
+ * Returns true if JavaScript for this plugin is loaded.
171
+ */
172
  function wpcf7_load_js() {
173
  return apply_filters( 'wpcf7_load_js', WPCF7_LOAD_JS );
174
  }
175
 
176
+
177
+ /**
178
+ * Returns true if CSS for this plugin is loaded.
179
+ */
180
  function wpcf7_load_css() {
181
  return apply_filters( 'wpcf7_load_css', WPCF7_LOAD_CSS );
182
  }
183
 
184
+
185
+ /**
186
+ * Returns a formatted string of HTML attributes.
187
+ *
188
+ * @param array $atts Associative array of attribute name and value pairs.
189
+ * @return string Formatted HTML attributes.
190
+ */
191
  function wpcf7_format_atts( $atts ) {
192
  $html = '';
193
 
220
  return $html;
221
  }
222
 
223
+
224
+ /**
225
+ * Builds an HTML anchor element.
226
+ *
227
+ * @param string $url Link URL.
228
+ * @param string $anchor_text Anchor label text.
229
+ * @param string|array $args Optional. Link options.
230
+ * @return string Formatted anchor element.
231
+ */
232
  function wpcf7_link( $url, $anchor_text, $args = '' ) {
233
  $defaults = array(
234
  'id' => '',
242
  $link = sprintf( '<a href="%1$s"%3$s>%2$s</a>',
243
  esc_url( $url ),
244
  esc_html( $anchor_text ),
245
+ $atts ? ( ' ' . $atts ) : ''
246
+ );
247
 
248
  return $link;
249
  }
250
 
251
+
252
+ /**
253
+ * Returns the current request URL.
254
+ */
255
  function wpcf7_get_request_uri() {
256
  static $request_uri = '';
257
 
262
  return esc_url_raw( $request_uri );
263
  }
264
 
265
+
266
+ /**
267
+ * Registers post types used for this plugin.
268
+ */
269
  function wpcf7_register_post_types() {
270
  if ( class_exists( 'WPCF7_ContactForm' ) ) {
271
  WPCF7_ContactForm::register_post_type();
275
  }
276
  }
277
 
278
+
279
+ /**
280
+ * Returns the version string of this plugin.
281
+ *
282
+ * @param string|array $args Optional. Output options.
283
+ * @return string Version string.
284
+ */
285
  function wpcf7_version( $args = '' ) {
286
  $defaults = array(
287
  'limit' => -1,
312
  return $ver;
313
  }
314
 
315
+
316
+ /**
317
+ * Returns array entries that match the given version.
318
+ *
319
+ * @param string $version The version to search for.
320
+ * @param array $input Search target array.
321
+ * @return array|bool Array of matched entries. False on failure.
322
+ */
323
  function wpcf7_version_grep( $version, array $input ) {
324
  $pattern = '/^' . preg_quote( (string) $version, '/' ) . '(?:\.|$)/';
325
 
326
  return preg_grep( $pattern, $input );
327
  }
328
 
329
+
330
+ /**
331
+ * Returns an enctype attribute value.
332
+ *
333
+ * @param string $enctype Enctype value.
334
+ * @return string Enctype value. Empty if not a valid enctype.
335
+ */
336
  function wpcf7_enctype_value( $enctype ) {
337
  $enctype = trim( $enctype );
338
 
359
  return '';
360
  }
361
 
362
+
363
+ /**
364
+ * Removes directory recursively.
365
+ *
366
+ * @param string $dir Directory path.
367
+ * @return bool True on success, false on failure.
368
+ */
369
  function wpcf7_rmdir_p( $dir ) {
370
  if ( is_file( $dir ) ) {
371
  $file = $dir;
412
  return false;
413
  }
414
 
415
+
416
+ /**
417
+ * Builds a URL-encoded query string.
418
+ *
419
+ * @see https://developer.wordpress.org/reference/functions/_http_build_query/
420
+ *
421
+ * @param array $args URL query parameters.
422
+ * @param string $key Optional. If specified, used to prefix key name.
423
+ * @return string Query string.
424
+ */
425
  function wpcf7_build_query( $args, $key = '' ) {
426
  $sep = '&';
427
  $ret = array();
449
  return implode( $sep, $ret );
450
  }
451
 
452
+
453
  /**
454
  * Returns the number of code units in a string.
455
  *
456
  * @see http://www.w3.org/TR/html5/infrastructure.html#code-unit-length
457
  *
458
+ * @param string $string Input string.
459
+ * @return int|bool The number of code units, or false if
460
+ * mb_convert_encoding is not available.
461
  */
462
  function wpcf7_count_code_units( $string ) {
463
  static $use_mb = null;
486
  return floor( $byte_count / 2 );
487
  }
488
 
489
+
490
+ /**
491
+ * Returns true if WordPress is running on the localhost.
492
+ */
493
  function wpcf7_is_localhost() {
494
  $server_name = strtolower( $_SERVER['SERVER_NAME'] );
495
  return in_array( $server_name, array( 'localhost', '127.0.0.1' ) );
496
  }
497
 
498
+
499
+ /**
500
+ * Marks a function as deprecated and informs when it has been used.
501
+ *
502
+ * @param string $function The function that was called.
503
+ * @param string $version The version of Contact Form 7 that deprecated
504
+ * the function.
505
+ * @param string $replacement The function that should have been called.
506
+ */
507
  function wpcf7_deprecated_function( $function, $version, $replacement ) {
508
  if ( WP_DEBUG ) {
509
  if ( function_exists( '__' ) ) {
527
  }
528
  }
529
 
530
+
531
+ /**
532
+ * Fires functions attached to a deprecated filter hook.
533
+ *
534
+ * @param string $tag The name of the filter hook.
535
+ * @param array $args Array of additional function arguments to be
536
+ * passed to apply_filters().
537
+ * @param string $version The version of Contact Form 7 that deprecated
538
+ * the hook.
539
+ * @param string $replacement The hook that should have been used.
540
+ */
541
  function wpcf7_apply_filters_deprecated( $tag, $args, $version, $replacement ) {
542
  if ( ! has_filter( $tag ) ) {
543
  return $args[0];
557
  return apply_filters_ref_array( $tag, $args );
558
  }
559
 
560
+
561
+ /**
562
+ * Marks something as being incorrectly called.
563
+ *
564
+ * @param string $function The function that was called.
565
+ * @param string $message A message explaining what has been done incorrectly.
566
+ * @param string $version The version of Contact Form 7 where the message
567
+ * was added.
568
+ */
569
  function wpcf7_doing_it_wrong( $function, $message, $version ) {
570
  if ( WP_DEBUG ) {
571
  if ( function_exists( '__' ) ) {
608
  }
609
  }
610
 
611
+
612
+ /**
613
+ * Triggers an error about a remote HTTP request and response.
614
+ *
615
+ * @param string $url The resource URL.
616
+ * @param array $request Request arguments.
617
+ * @param array|WP_Error $response The response or WP_Error on failure.
618
+ */
619
  function wpcf7_log_remote_request( $url, $request, $response ) {
620
  $log = sprintf(
621
  /* translators: 1: response code, 2: message, 3: body, 4: URL */
635
  }
636
  }
637
 
638
+
639
+ /**
640
+ * Anonymizes an IP address by masking local part.
641
+ *
642
+ * @param string $ip_addr The original IP address.
643
+ * @return string|bool Anonymized IP address, or false on failure.
644
+ */
645
  function wpcf7_anonymize_ip_addr( $ip_addr ) {
646
  if ( ! function_exists( 'inet_ntop' )
647
  or ! function_exists( 'inet_pton' ) ) {
includes/js/index.js CHANGED
@@ -1 +1 @@
1
- !function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=3)}([function(e,t){e.exports=function(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e},e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t,n){var r=n(2);e.exports=function(e,t){if(null==e)return{};var n,o,a=r(e,t);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(o=0;o<c.length;o++)n=c[o],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a},e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t){e.exports=function(e,t){if(null==e)return{};var n,r,o={},a=Object.keys(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)>=0||(o[n]=e[n]);return o},e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t,n){"use strict";n.r(t);var r=function(e){return Math.abs(parseInt(e,10))},o=function(e,t){var n=new Map([["init","init"],["validation_failed","invalid"],["acceptance_missing","unaccepted"],["spam","spam"],["aborted","aborted"],["mail_sent","sent"],["mail_failed","failed"],["submitting","submitting"],["resetting","resetting"]]);n.has(t)&&(t=n.get(t)),Array.from(n.values()).includes(t)||(t=(t=t.replace(/[^0-9a-z]+/i," ").trim()).replace(/\s+/,"-"),t="custom-".concat(t));var r=e.getAttribute("data-status");return e.wpcf7.status=t,e.setAttribute("data-status",t),e.classList.add(t),r&&r!==t&&e.classList.remove(r),t},a=function(e,t,n){var r=new CustomEvent("wpcf7".concat(t),{bubbles:!0,detail:n});"string"==typeof e&&(e=document.querySelector(e)),e.dispatchEvent(r)},c=n(0),i=n.n(c),s=n(1),u=n.n(s);function l(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function f(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?l(Object(n),!0).forEach((function(t){i()(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):l(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}var p=function(e){var t=wpcf7.api,n=t.root,r=t.namespace,o=void 0===r?"contact-form-7/v1":r;return d.reduceRight((function(e,t){return function(n){return t(n,e)}}),(function(e){var t,r,a=e.url,c=e.path,i=e.endpoint,s=e.headers,l=e.body,p=e.data,d=u()(e,["url","path","endpoint","headers","body","data"]);"string"==typeof i&&(t=o.replace(/^\/|\/$/g,""),c=(r=i.replace(/^\//,""))?t+"/"+r:t),"string"==typeof c&&(-1!==n.indexOf("?")&&(c=c.replace("?","&")),c=c.replace(/^\//,""),a=n+c),delete(s=f({Accept:"application/json, */*;q=0.1"},s))["X-WP-Nonce"],p&&(l=JSON.stringify(p),s["Content-Type"]="application/json");var v={code:"fetch_error",message:"You are probably offline."},b={code:"invalid_json",message:"The response is not a valid JSON response."};return window.fetch(a||c||window.location.href,f(f({},d),{},{headers:s,body:l})).then((function(e){return Promise.resolve(e).then((function(e){if(e.status>=200&&e.status<300)return e;throw e})).then((function(e){if(204===e.status)return null;if(e&&e.json)return e.json().catch((function(){throw b}));throw b}))}),(function(){throw v}))}))(e)},d=[];function v(e,t={}){const n=new FormData(e);t.submitter&&t.submitter.name&&n.append(t.submitter.name,t.submitter.value);const r={contactFormId:e.wpcf7.id,pluginVersion:e.wpcf7.pluginVersion,contactFormLocale:e.wpcf7.locale,unitTag:e.wpcf7.unitTag,containerPostId:e.wpcf7.containerPost,status:e.wpcf7.status,inputs:Array.from(n,e=>{const t=e[0],n=e[1];return!t.match(/^_/)&&{name:t,value:n}}).filter(e=>!1!==e),formData:n},c=t=>{const n=document.createElement("li");n.setAttribute("id",t.error_id),t.idref?n.insertAdjacentHTML("beforeend",`<a href="#${t.idref}">${t.message}</a>`):n.insertAdjacentText("beforeend",t.message),e.wpcf7.parent.querySelector(".screen-reader-response ul").appendChild(n)},i=t=>{const n=e.querySelector(t.into),r=n.querySelector(".wpcf7-form-control");r.classList.add("wpcf7-not-valid"),r.setAttribute("aria-describedby",t.error_id);const o=document.createElement("span");o.setAttribute("class","wpcf7-not-valid-tip"),o.setAttribute("aria-hidden","true"),o.insertAdjacentText("beforeend",t.message),n.appendChild(o),n.querySelectorAll("[aria-invalid]").forEach(e=>{e.setAttribute("aria-invalid","true")}),r.closest(".use-floating-validation-tip")&&(r.addEventListener("focus",e=>{o.setAttribute("style","display: none")}),o.addEventListener("mouseover",e=>{o.setAttribute("style","display: none")}))};p({endpoint:`contact-forms/${e.wpcf7.id}/feedback`,method:"POST",body:n,wpcf7:{endpoint:"feedback",form:e,detail:r}}).then(t=>{const n=o(e,t.status);return r.status=t.status,r.apiResponse=t,["invalid","unaccepted","spam","aborted"].includes(n)?a(e,n,r):["sent","failed"].includes(n)&&a(e,"mail"+n,r),a(e,"submit",r),t}).then(t=>{t.posted_data_hash&&(e.querySelector('input[name="_wpcf7_posted_data_hash"]').value=t.posted_data_hash),"mail_sent"===t.status&&(e.reset(),e.wpcf7.resetOnMailSent=!0),t.invalid_fields&&(t.invalid_fields.forEach(c),t.invalid_fields.forEach(i)),e.wpcf7.parent.querySelector('.screen-reader-response [role="status"]').insertAdjacentText("beforeend",t.message),e.querySelectorAll(".wpcf7-response-output").forEach(e=>{e.innerText=t.message})}).catch(e=>console.error(e))}p.use=function(e){d.unshift(e)},p.use((e,t)=>{if(e.wpcf7&&"feedback"===e.wpcf7.endpoint){const{form:t,detail:n}=e.wpcf7;b(t),a(t,"beforesubmit",n),o(t,"submitting")}return t(e)});const b=e=>{e.wpcf7.parent.querySelector('.screen-reader-response [role="status"]').innerText="",e.wpcf7.parent.querySelector(".screen-reader-response ul").innerText="",e.querySelectorAll(".wpcf7-not-valid-tip").forEach(e=>{e.remove()}),e.querySelectorAll("[aria-invalid]").forEach(e=>{e.setAttribute("aria-invalid","false")}),e.querySelectorAll(".wpcf7-form-control").forEach(e=>{e.removeAttribute("aria-describedby"),e.classList.remove("wpcf7-not-valid")}),e.querySelectorAll(".wpcf7-response-output").forEach(e=>{e.innerText=""})};function w(e){var t=new FormData(e),n={contactFormId:e.wpcf7.id,pluginVersion:e.wpcf7.pluginVersion,contactFormLocale:e.wpcf7.locale,unitTag:e.wpcf7.unitTag,containerPostId:e.wpcf7.containerPost,status:e.wpcf7.status,inputs:Array.from(t,(function(e){var t=e[0],n=e[1];return!t.match(/^_/)&&{name:t,value:n}})).filter((function(e){return!1!==e})),formData:t};p({endpoint:"contact-forms/".concat(e.wpcf7.id,"/refill"),method:"GET",wpcf7:{endpoint:"refill",form:e,detail:n}}).then((function(t){e.wpcf7.resetOnMailSent?(delete e.wpcf7.resetOnMailSent,o(e,"mail_sent")):o(e,"init"),n.apiResponse=t,a(e,"reset",n)})).catch((function(e){return console.error(e)}))}p.use((function(e,t){if(e.wpcf7&&"refill"===e.wpcf7.endpoint){var n=e.wpcf7,r=n.form;n.detail,b(r),o(r,"resetting")}return t(e)}));var m=function(e,t){var n=function(n){var r=t[n];e.querySelectorAll('input[name="'.concat(n,'"]')).forEach((function(e){e.value=""})),e.querySelectorAll("img.wpcf7-captcha-".concat(n)).forEach((function(e){e.setAttribute("src",r)}));var o=/([0-9]+)\.(png|gif|jpeg)$/.exec(r);o&&e.querySelectorAll('input[name="_wpcf7_captcha_challenge_'.concat(n,'"]')).forEach((function(e){e.value=o[1]}))};for(var r in t)n(r)},h=function(e,t){var n=function(n){var r=t[n][0],o=t[n][1];e.querySelectorAll(".wpcf7-form-control-wrap.".concat(n)).forEach((function(e){e.querySelector('input[name="'.concat(n,'"]')).value="",e.querySelector(".wpcf7-quiz-label").textContent=r,e.querySelector('input[name="_wpcf7_quiz_answer_'.concat(n,'"]')).value=o}))};for(var r in t)n(r)};function y(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function g(e){var t=new FormData(e);e.wpcf7={id:r(t.get("_wpcf7")),status:e.getAttribute("data-status"),pluginVersion:t.get("_wpcf7_version"),locale:t.get("_wpcf7_locale"),unitTag:t.get("_wpcf7_unit_tag"),containerPost:r(t.get("_wpcf7_container_post")),parent:e.closest(".wpcf7")},e.querySelectorAll(".wpcf7-submit").forEach((function(e){e.insertAdjacentHTML("afterend",'<span class="ajax-loader"></span>')})),function(e){e.querySelectorAll(".wpcf7-exclusive-checkbox").forEach((function(t){t.addEventListener("change",(function(t){var n=t.target.getAttribute("name");e.querySelectorAll('input[type="checkbox"][name="'.concat(n,'"]')).forEach((function(e){e!==t.target&&(e.checked=!1)}))}))}))}(e),function(e){e.querySelectorAll(".has-free-text").forEach((function(t){var n=t.querySelector("input.wpcf7-free-text"),r=t.querySelector('input[type="checkbox"], input[type="radio"]');n.disabled=!r.checked,e.addEventListener("change",(function(e){n.disabled=!r.checked,e.target===r&&r.checked&&n.focus()}))}))}(e),function(e){e.querySelectorAll(".wpcf7-validates-as-url").forEach((function(e){e.addEventListener("change",(function(t){var n=e.value.trim();n&&!n.match(/^[a-z][a-z0-9.+-]*:/i)&&-1!==n.indexOf(".")&&(n="http://"+(n=n.replace(/^\/+/,""))),e.value=n}))}))}(e),function(e){if(e.querySelector(".wpcf7-acceptance")&&!e.classList.contains("wpcf7-acceptance-as-validation")){var t=function(){var t=!0;e.querySelectorAll(".wpcf7-acceptance").forEach((function(e){if(t&&!e.classList.contains("optional")){var n=e.querySelector('input[type="checkbox"]');(e.classList.contains("invert")&&n.checked||!e.classList.contains("invert")&&!n.checked)&&(t=!1)}})),e.querySelectorAll(".wpcf7-submit").forEach((function(e){e.disabled=!t}))};t(),e.addEventListener("change",(function(e){t()})),e.addEventListener("wpcf7reset",(function(e){t()}))}}(e),function(e){var t=function(e,t){var n=r(e.getAttribute("data-starting-value")),o=r(e.getAttribute("data-maximum-value")),a=r(e.getAttribute("data-minimum-value")),c=e.classList.contains("down")?n-t.value.length:t.value.length;e.setAttribute("data-current-value",c),e.innerText=c,o&&o<t.value.length?e.classList.add("too-long"):e.classList.remove("too-long"),a&&t.value.length<a?e.classList.add("too-short"):e.classList.remove("too-short")},n=function(n){n=function(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?y(Object(n),!0).forEach((function(t){i()(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):y(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}({init:!1},n),e.querySelectorAll(".wpcf7-character-count").forEach((function(r){var o=r.getAttribute("data-target-name"),a=e.querySelector('[name="'.concat(o,'"]'));a&&(a.value=a.defaultValue,t(r,a),n.init&&a.addEventListener("keyup",(function(e){t(r,a)})))}))};n({init:!0}),e.addEventListener("wpcf7reset",(function(e){n()}))}(e),window.addEventListener("load",(function(t){wpcf7.cached&&e.reset()})),e.addEventListener("reset",(function(t){wpcf7.reset(e)})),e.addEventListener("submit",(function(t){var n=t.submitter;wpcf7.submit(e,{submitter:n}),t.preventDefault()})),e.addEventListener("wpcf7submit",(function(t){t.detail.apiResponse.captcha&&m(e,t.detail.apiResponse.captcha),t.detail.apiResponse.quiz&&h(e,t.detail.apiResponse.quiz)})),e.addEventListener("wpcf7reset",(function(t){t.detail.apiResponse.captcha&&m(e,t.detail.apiResponse.captcha),t.detail.apiResponse.quiz&&h(e,t.detail.apiResponse.quiz)}))}document.addEventListener("DOMContentLoaded",e=>{var t;if("undefined"==typeof wpcf7)return void console.error("wpcf7 is not defined.");if(void 0===wpcf7.api)return void console.error("wpcf7.api is not defined.");if("function"!=typeof window.fetch)return void console.error("Your browser doesn't support window.fetch().");if("function"!=typeof window.FormData)return void console.error("Your browser doesn't support window.FormData().");const n=document.querySelectorAll(".wpcf7 > form");"function"==typeof n.forEach?(wpcf7={init:g,submit:v,reset:w,...null!==(t=wpcf7)&&void 0!==t?t:{}},n.forEach(e=>wpcf7.init(e))):console.error("Your browser doesn't support NodeList.forEach().")})}]);
1
+ !function(){"use strict";var e=function(e){return Math.abs(parseInt(e,10))};const t=(e,t)=>{const n=new Map([["init","init"],["validation_failed","invalid"],["acceptance_missing","unaccepted"],["spam","spam"],["aborted","aborted"],["mail_sent","sent"],["mail_failed","failed"],["submitting","submitting"],["resetting","resetting"],["payment_required","payment-required"]]);n.has(t)&&(t=n.get(t)),Array.from(n.values()).includes(t)||(t=`custom-${t=(t=t.replace(/[^0-9a-z]+/i," ").trim()).replace(/\s+/,"-")}`);const r=e.getAttribute("data-status");return e.wpcf7.status=t,e.setAttribute("data-status",t),e.classList.add(t),r&&r!==t&&e.classList.remove(r),t};var n=function(e,t,n){var r=new CustomEvent("wpcf7".concat(t),{bubbles:!0,detail:n});"string"==typeof e&&(e=document.querySelector(e)),e.dispatchEvent(r)};function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function c(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?a(Object(n),!0).forEach((function(t){r(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):a(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}var o=function(e){var t=wpcf7.api,n=t.root,r=t.namespace,a=void 0===r?"contact-form-7/v1":r;return i.reduceRight((function(e,t){return function(n){return t(n,e)}}),(function(e){var t,r,o=e.url,i=e.path,s=e.endpoint,u=e.headers,l=e.body,f=e.data,p=function(e,t){if(null==e)return{};var n,r,a=function(e,t){if(null==e)return{};var n,r,a={},c=Object.keys(e);for(r=0;r<c.length;r++)n=c[r],t.indexOf(n)>=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(r=0;r<c.length;r++)n=c[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}(e,["url","path","endpoint","headers","body","data"]);"string"==typeof s&&(t=a.replace(/^\/|\/$/g,""),i=(r=s.replace(/^\//,""))?t+"/"+r:t),"string"==typeof i&&(-1!==n.indexOf("?")&&(i=i.replace("?","&")),i=i.replace(/^\//,""),o=n+i),delete(u=c({Accept:"application/json, */*;q=0.1"},u))["X-WP-Nonce"],f&&(l=JSON.stringify(f),u["Content-Type"]="application/json");var d={code:"fetch_error",message:"You are probably offline."},w={code:"invalid_json",message:"The response is not a valid JSON response."};return window.fetch(o||i||window.location.href,c(c({},p),{},{headers:u,body:l})).then((function(e){return Promise.resolve(e).then((function(e){if(e.status>=200&&e.status<300)return e;throw e})).then((function(e){if(204===e.status)return null;if(e&&e.json)return e.json().catch((function(){throw w}));throw w}))}),(function(){throw d}))}))(e)},i=[];function s(e,r={}){if(wpcf7.blocked)return u(e),void t(e,"submitting");const a=new FormData(e);r.submitter&&r.submitter.name&&a.append(r.submitter.name,r.submitter.value);const c={contactFormId:e.wpcf7.id,pluginVersion:e.wpcf7.pluginVersion,contactFormLocale:e.wpcf7.locale,unitTag:e.wpcf7.unitTag,containerPostId:e.wpcf7.containerPost,status:e.wpcf7.status,inputs:Array.from(a,(e=>{const t=e[0],n=e[1];return!t.match(/^_/)&&{name:t,value:n}})).filter((e=>!1!==e)),formData:a},i=t=>{const n=document.createElement("li");n.setAttribute("id",t.error_id),t.idref?n.insertAdjacentHTML("beforeend",`<a href="#${t.idref}">${t.message}</a>`):n.insertAdjacentText("beforeend",t.message),e.wpcf7.parent.querySelector(".screen-reader-response ul").appendChild(n)},s=t=>{const n=e.querySelector(t.into),r=n.querySelector(".wpcf7-form-control");r.classList.add("wpcf7-not-valid"),r.setAttribute("aria-describedby",t.error_id);const a=document.createElement("span");a.setAttribute("class","wpcf7-not-valid-tip"),a.setAttribute("aria-hidden","true"),a.insertAdjacentText("beforeend",t.message),n.appendChild(a),n.querySelectorAll("[aria-invalid]").forEach((e=>{e.setAttribute("aria-invalid","true")})),r.closest(".use-floating-validation-tip")&&(r.addEventListener("focus",(e=>{a.setAttribute("style","display: none")})),a.addEventListener("mouseover",(e=>{a.setAttribute("style","display: none")})))};o({endpoint:`contact-forms/${e.wpcf7.id}/feedback`,method:"POST",body:a,wpcf7:{endpoint:"feedback",form:e,detail:c}}).then((r=>{const a=t(e,r.status);return c.status=r.status,c.apiResponse=r,["invalid","unaccepted","spam","aborted"].includes(a)?n(e,a,c):["sent","failed"].includes(a)&&n(e,`mail${a}`,c),n(e,"submit",c),r})).then((t=>{t.posted_data_hash&&(e.querySelector('input[name="_wpcf7_posted_data_hash"]').value=t.posted_data_hash),"mail_sent"===t.status&&(e.reset(),e.wpcf7.resetOnMailSent=!0),t.invalid_fields&&(t.invalid_fields.forEach(i),t.invalid_fields.forEach(s)),e.wpcf7.parent.querySelector('.screen-reader-response [role="status"]').insertAdjacentText("beforeend",t.message),e.querySelectorAll(".wpcf7-response-output").forEach((e=>{e.innerText=t.message}))})).catch((e=>console.error(e)))}o.use=function(e){i.unshift(e)},o.use(((e,r)=>{if(e.wpcf7&&"feedback"===e.wpcf7.endpoint){const{form:r,detail:a}=e.wpcf7;u(r),n(r,"beforesubmit",a),t(r,"submitting")}return r(e)}));const u=e=>{e.wpcf7.parent.querySelector('.screen-reader-response [role="status"]').innerText="",e.wpcf7.parent.querySelector(".screen-reader-response ul").innerText="",e.querySelectorAll(".wpcf7-not-valid-tip").forEach((e=>{e.remove()})),e.querySelectorAll("[aria-invalid]").forEach((e=>{e.setAttribute("aria-invalid","false")})),e.querySelectorAll(".wpcf7-form-control").forEach((e=>{e.removeAttribute("aria-describedby"),e.classList.remove("wpcf7-not-valid")})),e.querySelectorAll(".wpcf7-response-output").forEach((e=>{e.innerText=""}))};function l(e){var r=new FormData(e),a={contactFormId:e.wpcf7.id,pluginVersion:e.wpcf7.pluginVersion,contactFormLocale:e.wpcf7.locale,unitTag:e.wpcf7.unitTag,containerPostId:e.wpcf7.containerPost,status:e.wpcf7.status,inputs:Array.from(r,(function(e){var t=e[0],n=e[1];return!t.match(/^_/)&&{name:t,value:n}})).filter((function(e){return!1!==e})),formData:r};o({endpoint:"contact-forms/".concat(e.wpcf7.id,"/refill"),method:"GET",wpcf7:{endpoint:"refill",form:e,detail:a}}).then((function(r){e.wpcf7.resetOnMailSent?(delete e.wpcf7.resetOnMailSent,t(e,"mail_sent")):t(e,"init"),a.apiResponse=r,n(e,"reset",a)})).catch((function(e){return console.error(e)}))}o.use((function(e,n){if(e.wpcf7&&"refill"===e.wpcf7.endpoint){var r=e.wpcf7,a=r.form;r.detail,u(a),t(a,"resetting")}return n(e)}));var f=function(e,t){var n=function(n){var r=t[n];e.querySelectorAll('input[name="'.concat(n,'"]')).forEach((function(e){e.value=""})),e.querySelectorAll("img.wpcf7-captcha-".concat(n)).forEach((function(e){e.setAttribute("src",r)}));var a=/([0-9]+)\.(png|gif|jpeg)$/.exec(r);a&&e.querySelectorAll('input[name="_wpcf7_captcha_challenge_'.concat(n,'"]')).forEach((function(e){e.value=a[1]}))};for(var r in t)n(r)},p=function(e,t){var n=function(n){var r=t[n][0],a=t[n][1];e.querySelectorAll(".wpcf7-form-control-wrap.".concat(n)).forEach((function(e){e.querySelector('input[name="'.concat(n,'"]')).value="",e.querySelector(".wpcf7-quiz-label").textContent=r,e.querySelector('input[name="_wpcf7_quiz_answer_'.concat(n,'"]')).value=a}))};for(var r in t)n(r)};function d(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function w(t){const n=new FormData(t);t.wpcf7={id:e(n.get("_wpcf7")),status:t.getAttribute("data-status"),pluginVersion:n.get("_wpcf7_version"),locale:n.get("_wpcf7_locale"),unitTag:n.get("_wpcf7_unit_tag"),containerPost:e(n.get("_wpcf7_container_post")),parent:t.closest(".wpcf7")},t.querySelectorAll(".has-spinner").forEach((e=>{e.insertAdjacentHTML("afterend",'<span class="wpcf7-spinner"></span>')})),function(e){e.querySelectorAll(".wpcf7-exclusive-checkbox").forEach((function(t){t.addEventListener("change",(function(t){var n=t.target.getAttribute("name");e.querySelectorAll('input[type="checkbox"][name="'.concat(n,'"]')).forEach((function(e){e!==t.target&&(e.checked=!1)}))}))}))}(t),function(e){e.querySelectorAll(".has-free-text").forEach((function(t){var n=t.querySelector("input.wpcf7-free-text"),r=t.querySelector('input[type="checkbox"], input[type="radio"]');n.disabled=!r.checked,e.addEventListener("change",(function(e){n.disabled=!r.checked,e.target===r&&r.checked&&n.focus()}))}))}(t),function(e){e.querySelectorAll(".wpcf7-validates-as-url").forEach((function(e){e.addEventListener("change",(function(t){var n=e.value.trim();n&&!n.match(/^[a-z][a-z0-9.+-]*:/i)&&-1!==n.indexOf(".")&&(n="http://"+(n=n.replace(/^\/+/,""))),e.value=n}))}))}(t),function(e){if(e.querySelector(".wpcf7-acceptance")&&!e.classList.contains("wpcf7-acceptance-as-validation")){var t=function(){var t=!0;e.querySelectorAll(".wpcf7-acceptance").forEach((function(e){if(t&&!e.classList.contains("optional")){var n=e.querySelector('input[type="checkbox"]');(e.classList.contains("invert")&&n.checked||!e.classList.contains("invert")&&!n.checked)&&(t=!1)}})),e.querySelectorAll(".wpcf7-submit").forEach((function(e){e.disabled=!t}))};t(),e.addEventListener("change",(function(e){t()})),e.addEventListener("wpcf7reset",(function(e){t()}))}}(t),function(t){var n=function(t,n){var r=e(t.getAttribute("data-starting-value")),a=e(t.getAttribute("data-maximum-value")),c=e(t.getAttribute("data-minimum-value")),o=t.classList.contains("down")?r-n.value.length:n.value.length;t.setAttribute("data-current-value",o),t.innerText=o,a&&a<n.value.length?t.classList.add("too-long"):t.classList.remove("too-long"),c&&n.value.length<c?t.classList.add("too-short"):t.classList.remove("too-short")},a=function(e){e=function(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?d(Object(n),!0).forEach((function(t){r(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):d(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}({init:!1},e),t.querySelectorAll(".wpcf7-character-count").forEach((function(r){var a=r.getAttribute("data-target-name"),c=t.querySelector('[name="'.concat(a,'"]'));c&&(c.value=c.defaultValue,n(r,c),e.init&&c.addEventListener("keyup",(function(e){n(r,c)})))}))};a({init:!0}),t.addEventListener("wpcf7reset",(function(e){a()}))}(t),window.addEventListener("load",(e=>{wpcf7.cached&&t.reset()})),t.addEventListener("reset",(e=>{wpcf7.reset(t)})),t.addEventListener("submit",(e=>{const n=e.submitter;wpcf7.submit(t,{submitter:n}),e.preventDefault()})),t.addEventListener("wpcf7submit",(e=>{e.detail.apiResponse.captcha&&f(t,e.detail.apiResponse.captcha),e.detail.apiResponse.quiz&&p(t,e.detail.apiResponse.quiz)})),t.addEventListener("wpcf7reset",(e=>{e.detail.apiResponse.captcha&&f(t,e.detail.apiResponse.captcha),e.detail.apiResponse.quiz&&p(t,e.detail.apiResponse.quiz)}))}document.addEventListener("DOMContentLoaded",(e=>{var t;if("undefined"==typeof wpcf7)return void console.error("wpcf7 is not defined.");if(void 0===wpcf7.api)return void console.error("wpcf7.api is not defined.");if("function"!=typeof window.fetch)return void console.error("Your browser doesn't support window.fetch().");if("function"!=typeof window.FormData)return void console.error("Your browser doesn't support window.FormData().");const n=document.querySelectorAll(".wpcf7 > form");"function"==typeof n.forEach?(wpcf7={init:w,submit:s,reset:l,...null!==(t=wpcf7)&&void 0!==t?t:{}},n.forEach((e=>wpcf7.init(e)))):console.error("Your browser doesn't support NodeList.forEach().")}))}();
includes/mail.php CHANGED
@@ -373,7 +373,9 @@ class WPCF7_MailTaggedText {
373
  : null;
374
 
375
  if ( $mail_tag->get_option( 'do_not_heat' ) ) {
376
- $submitted = isset( $_POST[$field_name] ) ? $_POST[$field_name] : '';
 
 
377
  }
378
 
379
  $replaced = $submitted;
@@ -406,7 +408,7 @@ class WPCF7_MailTaggedText {
406
  );
407
 
408
  if ( null !== $replaced ) {
409
- $replaced = wp_unslash( trim( $replaced ) );
410
 
411
  $this->replaced_tags[$tag] = $replaced;
412
  return $replaced;
@@ -480,7 +482,7 @@ class WPCF7_MailTag {
480
  }
481
 
482
  public function field_name() {
483
- return $this->name;
484
  }
485
 
486
  public function get_option( $option ) {
@@ -499,7 +501,7 @@ class WPCF7_MailTag {
499
  if ( $submission = WPCF7_Submission::get_instance() ) {
500
  $contact_form = $submission->get_contact_form();
501
  $tags = $contact_form->scan_form_tags( array(
502
- 'name' => $this->name,
503
  'feature' => '! zero-controls-container',
504
  ) );
505
 
373
  : null;
374
 
375
  if ( $mail_tag->get_option( 'do_not_heat' ) ) {
376
+ $submitted = isset( $_POST[$field_name] )
377
+ ? wp_unslash( $_POST[$field_name] )
378
+ : '';
379
  }
380
 
381
  $replaced = $submitted;
408
  );
409
 
410
  if ( null !== $replaced ) {
411
+ $replaced = trim( $replaced );
412
 
413
  $this->replaced_tags[$tag] = $replaced;
414
  return $replaced;
482
  }
483
 
484
  public function field_name() {
485
+ return strtr( $this->name, '.', '_' );
486
  }
487
 
488
  public function get_option( $option ) {
501
  if ( $submission = WPCF7_Submission::get_instance() ) {
502
  $contact_form = $submission->get_contact_form();
503
  $tags = $contact_form->scan_form_tags( array(
504
+ 'name' => $this->field_name(),
505
  'feature' => '! zero-controls-container',
506
  ) );
507
 
includes/pipe.php CHANGED
@@ -34,14 +34,28 @@ class WPCF7_Pipes {
34
  $this->pipes[] = $pipe;
35
  }
36
 
37
- public function do_pipe( $before ) {
 
 
 
 
38
  foreach ( $this->pipes as $pipe ) {
39
- if ( $pipe->before == $before ) {
40
- return $pipe->after;
 
 
 
 
 
 
 
 
 
 
41
  }
42
  }
43
 
44
- return $before;
45
  }
46
 
47
  public function collect_befores() {
34
  $this->pipes[] = $pipe;
35
  }
36
 
37
+ public function do_pipe( $input ) {
38
+ $input_canonical = wpcf7_canonicalize( $input, array(
39
+ 'strto' => 'as-is',
40
+ ) );
41
+
42
  foreach ( $this->pipes as $pipe ) {
43
+
44
+ list( $before, $after ) = array_map(
45
+ function ( $item ) {
46
+ return wpcf7_canonicalize( $item, array(
47
+ 'strto' => 'as-is',
48
+ ) );
49
+ },
50
+ array( $pipe->before, $pipe->after )
51
+ );
52
+
53
+ if ( $input_canonical === $before ) {
54
+ return $after;
55
  }
56
  }
57
 
58
+ return $input;
59
  }
60
 
61
  public function collect_befores() {
includes/rest-api.php CHANGED
@@ -1,438 +1,468 @@
1
  <?php
2
 
3
- add_action( 'rest_api_init', 'wpcf7_rest_api_init', 10, 0 );
 
 
 
 
 
 
 
4
 
5
- function wpcf7_rest_api_init() {
6
- $namespace = 'contact-form-7/v1';
7
 
8
- register_rest_route( $namespace,
9
- '/contact-forms',
10
- array(
11
- array(
12
- 'methods' => WP_REST_Server::READABLE,
13
- 'callback' => 'wpcf7_rest_get_contact_forms',
14
- 'permission_callback' => function() {
15
- if ( current_user_can( 'wpcf7_read_contact_forms' ) ) {
16
- return true;
17
- } else {
18
- return new WP_Error( 'wpcf7_forbidden',
19
- __( "You are not allowed to access contact forms.", 'contact-form-7' ),
20
- array( 'status' => 403 )
21
- );
22
- }
23
- },
24
- ),
25
- array(
26
- 'methods' => WP_REST_Server::CREATABLE,
27
- 'callback' => 'wpcf7_rest_create_contact_form',
28
- 'permission_callback' => function() {
29
- if ( current_user_can( 'wpcf7_edit_contact_forms' ) ) {
30
- return true;
31
- } else {
32
- return new WP_Error( 'wpcf7_forbidden',
33
- __( "You are not allowed to create a contact form.", 'contact-form-7' ),
34
- array( 'status' => 403 )
35
- );
36
- }
37
- },
38
- ),
39
- )
40
- );
41
 
42
- register_rest_route( $namespace,
43
- '/contact-forms/(?P<id>\d+)',
44
- array(
45
- array(
46
- 'methods' => WP_REST_Server::READABLE,
47
- 'callback' => 'wpcf7_rest_get_contact_form',
48
- 'permission_callback' => function( WP_REST_Request $request ) {
49
- $id = (int) $request->get_param( 'id' );
50
-
51
- if ( current_user_can( 'wpcf7_edit_contact_form', $id ) ) {
52
- return true;
53
- } else {
54
- return new WP_Error( 'wpcf7_forbidden',
55
- __( "You are not allowed to access the requested contact form.", 'contact-form-7' ),
56
- array( 'status' => 403 )
57
- );
58
- }
59
- },
60
- ),
61
  array(
62
- 'methods' => WP_REST_Server::EDITABLE,
63
- 'callback' => 'wpcf7_rest_update_contact_form',
64
- 'permission_callback' => function( WP_REST_Request $request ) {
65
- $id = (int) $request->get_param( 'id' );
66
-
67
- if ( current_user_can( 'wpcf7_edit_contact_form', $id ) ) {
68
- return true;
69
- } else {
70
- return new WP_Error( 'wpcf7_forbidden',
71
- __( "You are not allowed to access the requested contact form.", 'contact-form-7' ),
72
- array( 'status' => 403 )
73
- );
74
- }
75
- },
76
- ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
  array(
78
- 'methods' => WP_REST_Server::DELETABLE,
79
- 'callback' => 'wpcf7_rest_delete_contact_form',
80
- 'permission_callback' => function( WP_REST_Request $request ) {
81
- $id = (int) $request->get_param( 'id' );
82
-
83
- if ( current_user_can( 'wpcf7_delete_contact_form', $id ) ) {
84
- return true;
85
- } else {
86
- return new WP_Error( 'wpcf7_forbidden',
87
- __( "You are not allowed to access the requested contact form.", 'contact-form-7' ),
88
- array( 'status' => 403 )
89
- );
90
- }
91
- },
92
- ),
93
- )
94
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
 
96
- register_rest_route( $namespace,
97
- '/contact-forms/(?P<id>\d+)/feedback',
98
- array(
99
  array(
100
- 'methods' => WP_REST_Server::CREATABLE,
101
- 'callback' => 'wpcf7_rest_create_feedback',
102
- 'permission_callback' => '__return_true',
103
- ),
104
- )
105
- );
 
 
106
 
107
- register_rest_route( $namespace,
108
- '/contact-forms/(?P<id>\d+)/refill',
109
- array(
110
  array(
111
- 'methods' => WP_REST_Server::READABLE,
112
- 'callback' => 'wpcf7_rest_get_refill',
113
- 'permission_callback' => '__return_true',
114
- ),
115
- )
116
- );
117
- }
 
 
118
 
119
- function wpcf7_rest_get_contact_forms( WP_REST_Request $request ) {
120
- $args = array();
121
 
122
- $per_page = $request->get_param( 'per_page' );
123
 
124
- if ( null !== $per_page ) {
125
- $args['posts_per_page'] = (int) $per_page;
126
- }
127
 
128
- $offset = $request->get_param( 'offset' );
129
 
130
- if ( null !== $offset ) {
131
- $args['offset'] = (int) $offset;
132
- }
133
 
134
- $order = $request->get_param( 'order' );
135
 
136
- if ( null !== $order ) {
137
- $args['order'] = (string) $order;
138
- }
139
 
140
- $orderby = $request->get_param( 'orderby' );
141
 
142
- if ( null !== $orderby ) {
143
- $args['orderby'] = (string) $orderby;
144
- }
 
 
 
 
 
 
145
 
146
- $search = $request->get_param( 'search' );
147
 
148
- if ( null !== $search ) {
149
- $args['s'] = (string) $search;
 
 
 
 
 
 
 
 
 
 
150
  }
151
 
152
- $items = WPCF7_ContactForm::find( $args );
 
153
 
154
- $response = array();
 
 
 
 
 
155
 
156
- foreach ( $items as $item ) {
157
- $response[] = array(
 
 
 
 
 
 
 
 
 
 
 
158
  'id' => $item->id(),
159
  'slug' => $item->name(),
160
  'title' => $item->title(),
161
  'locale' => $item->locale(),
 
 
162
  );
163
- }
164
 
165
- return rest_ensure_response( $response );
166
- }
 
167
 
168
- function wpcf7_rest_create_contact_form( WP_REST_Request $request ) {
169
- $id = (int) $request->get_param( 'id' );
170
 
171
- if ( $id ) {
172
- return new WP_Error( 'wpcf7_post_exists',
173
- __( "Cannot create existing contact form.", 'contact-form-7' ),
174
- array( 'status' => 400 )
175
- );
 
176
  }
177
 
178
- $args = $request->get_params();
179
- $args['id'] = -1; // Create
180
- $context = $request->get_param( 'context' );
181
- $item = wpcf7_save_contact_form( $args, $context );
182
 
183
- if ( ! $item ) {
184
- return new WP_Error( 'wpcf7_cannot_save',
185
- __( "There was an error saving the contact form.", 'contact-form-7' ),
186
- array( 'status' => 500 )
187
- );
188
- }
189
 
190
- $response = array(
191
- 'id' => $item->id(),
192
- 'slug' => $item->name(),
193
- 'title' => $item->title(),
194
- 'locale' => $item->locale(),
195
- 'properties' => wpcf7_get_properties_for_api( $item ),
196
- 'config_errors' => array(),
197
- );
198
 
199
- if ( wpcf7_validate_configuration() ) {
200
- $config_validator = new WPCF7_ConfigValidator( $item );
201
- $config_validator->validate();
202
 
203
- $response['config_errors'] = $config_validator->collect_error_messages();
 
 
204
 
205
- if ( 'save' == $context ) {
206
- $config_validator->save();
 
 
 
207
  }
208
- }
209
 
210
- return rest_ensure_response( $response );
211
- }
 
212
 
213
- function wpcf7_rest_get_contact_form( WP_REST_Request $request ) {
214
- $id = (int) $request->get_param( 'id' );
215
- $item = wpcf7_contact_form( $id );
 
 
 
216
 
217
- if ( ! $item ) {
218
- return new WP_Error( 'wpcf7_not_found',
219
- __( "The requested contact form was not found.", 'contact-form-7' ),
220
- array( 'status' => 404 )
 
 
 
221
  );
222
- }
223
 
224
- $response = array(
225
- 'id' => $item->id(),
226
- 'slug' => $item->name(),
227
- 'title' => $item->title(),
228
- 'locale' => $item->locale(),
229
- 'properties' => wpcf7_get_properties_for_api( $item ),
230
- );
231
 
232
- return rest_ensure_response( $response );
233
- }
234
 
235
- function wpcf7_rest_update_contact_form( WP_REST_Request $request ) {
236
- $id = (int) $request->get_param( 'id' );
237
- $item = wpcf7_contact_form( $id );
 
238
 
239
- if ( ! $item ) {
240
- return new WP_Error( 'wpcf7_not_found',
241
- __( "The requested contact form was not found.", 'contact-form-7' ),
242
- array( 'status' => 404 )
243
- );
244
  }
245
 
246
- $args = $request->get_params();
247
- $context = $request->get_param( 'context' );
248
- $item = wpcf7_save_contact_form( $args, $context );
249
 
250
- if ( ! $item ) {
251
- return new WP_Error( 'wpcf7_cannot_save',
252
- __( "There was an error saving the contact form.", 'contact-form-7' ),
253
- array( 'status' => 500 )
254
- );
255
- }
256
 
257
- $response = array(
258
- 'id' => $item->id(),
259
- 'slug' => $item->name(),
260
- 'title' => $item->title(),
261
- 'locale' => $item->locale(),
262
- 'properties' => wpcf7_get_properties_for_api( $item ),
263
- 'config_errors' => array(),
264
- );
265
 
266
- if ( wpcf7_validate_configuration() ) {
267
- $config_validator = new WPCF7_ConfigValidator( $item );
268
- $config_validator->validate();
 
 
 
269
 
270
- $response['config_errors'] = $config_validator->collect_error_messages();
271
 
272
- if ( 'save' == $context ) {
273
- $config_validator->save();
274
- }
275
  }
276
 
277
- return rest_ensure_response( $response );
278
- }
279
 
280
- function wpcf7_rest_delete_contact_form( WP_REST_Request $request ) {
281
- $id = (int) $request->get_param( 'id' );
282
- $item = wpcf7_contact_form( $id );
283
 
284
- if ( ! $item ) {
285
- return new WP_Error( 'wpcf7_not_found',
286
- __( "The requested contact form was not found.", 'contact-form-7' ),
287
- array( 'status' => 404 )
288
- );
289
- }
290
 
291
- $result = $item->delete();
 
 
 
 
 
292
 
293
- if ( ! $result ) {
294
- return new WP_Error( 'wpcf7_cannot_delete',
295
- __( "There was an error deleting the contact form.", 'contact-form-7' ),
296
- array( 'status' => 500 )
297
  );
298
- }
299
 
300
- $response = array( 'deleted' => true );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
301
 
302
- return rest_ensure_response( $response );
303
- }
304
 
305
- function wpcf7_rest_create_feedback( WP_REST_Request $request ) {
306
- $url_params = $request->get_url_params();
 
 
 
 
307
 
308
- $item = null;
309
 
310
- if ( ! empty( $url_params['id'] ) ) {
311
- $item = wpcf7_contact_form( $url_params['id'] );
312
  }
313
 
314
- if ( ! $item ) {
315
- return new WP_Error( 'wpcf7_not_found',
316
- __( "The requested contact form was not found.", 'contact-form-7' ),
317
- array( 'status' => 404 )
318
- );
319
- }
320
 
321
- $result = $item->submit();
322
-
323
- $unit_tag = $request->get_param( '_wpcf7_unit_tag' );
324
-
325
- $response = array(
326
- 'into' => '#' . wpcf7_sanitize_unit_tag( $unit_tag ),
327
- 'status' => $result['status'],
328
- 'message' => $result['message'],
329
- 'posted_data_hash' => $result['posted_data_hash'],
330
- );
331
-
332
- if ( 'validation_failed' == $result['status'] ) {
333
- $invalid_fields = array();
334
-
335
- foreach ( (array) $result['invalid_fields'] as $name => $field ) {
336
- $invalid_fields[] = array(
337
- 'into' => 'span.wpcf7-form-control-wrap.'
338
- . sanitize_html_class( $name ),
339
- 'message' => $field['reason'],
340
- 'idref' => $field['idref'],
341
- 'error_id' => sprintf(
342
- '%1$s-ve-%2$s',
343
- $unit_tag,
344
- $name
345
- ),
346
  );
347
  }
348
 
349
- $response['invalid_fields'] = $invalid_fields;
350
- }
351
-
352
- $response = wpcf7_apply_filters_deprecated(
353
- 'wpcf7_ajax_json_echo',
354
- array( $response, $result ),
355
- '5.2',
356
- 'wpcf7_feedback_response'
357
- );
358
-
359
- $response = apply_filters( 'wpcf7_feedback_response', $response, $result );
360
 
361
- return rest_ensure_response( $response );
362
- }
363
 
364
- function wpcf7_rest_get_refill( WP_REST_Request $request ) {
365
- $id = (int) $request->get_param( 'id' );
366
- $item = wpcf7_contact_form( $id );
367
 
368
- if ( ! $item ) {
369
- return new WP_Error( 'wpcf7_not_found',
370
- __( "The requested contact form was not found.", 'contact-form-7' ),
371
- array( 'status' => 404 )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
372
  );
373
- }
374
 
375
- $response = wpcf7_apply_filters_deprecated(
376
- 'wpcf7_ajax_onload',
377
- array( array() ),
378
- '5.2',
379
- 'wpcf7_refill_response'
380
- );
381
 
382
- $response = apply_filters( 'wpcf7_refill_response', array() );
 
 
383
 
384
- return rest_ensure_response( $response );
385
- }
 
 
 
386
 
387
- function wpcf7_get_properties_for_api( WPCF7_ContactForm $contact_form ) {
388
- $properties = $contact_form->get_properties();
389
-
390
- $properties['form'] = array(
391
- 'content' => (string) $properties['form'],
392
- 'fields' => array_map(
393
- function( WPCF7_FormTag $form_tag ) {
394
- return array(
395
- 'type' => $form_tag->type,
396
- 'basetype' => $form_tag->basetype,
397
- 'name' => $form_tag->name,
398
- 'options' => $form_tag->options,
399
- 'raw_values' => $form_tag->raw_values,
400
- 'labels' => $form_tag->labels,
401
- 'values' => $form_tag->values,
402
- 'pipes' => $form_tag->pipes instanceof WPCF7_Pipes
403
- ? $form_tag->pipes->to_array()
404
- : $form_tag->pipes,
405
- 'content' => $form_tag->content,
406
- );
407
- },
408
- $contact_form->scan_form_tags()
409
- ),
410
- );
411
-
412
- $properties['additional_settings'] = array(
413
- 'content' => (string) $properties['additional_settings'],
414
- 'settings' => array_filter( array_map(
415
- function( $setting ) {
416
- $pattern = '/^([a-zA-Z0-9_]+)[\t ]*:(.*)$/';
417
-
418
- if ( preg_match( $pattern, $setting, $matches ) ) {
419
- $name = trim( $matches[1] );
420
- $value = trim( $matches[2] );
421
-
422
- if ( in_array( $value, array( 'on', 'true' ), true ) ) {
423
- $value = true;
424
- } elseif ( in_array( $value, array( 'off', 'false' ), true ) ) {
425
- $value = false;
426
  }
427
 
428
- return array( $name, $value );
429
- }
 
 
 
 
 
 
430
 
431
- return false;
432
- },
433
- explode( "\n", $properties['additional_settings'] )
434
- ) ),
435
- );
 
 
 
 
436
 
437
- return $properties;
438
  }
1
  <?php
2
 
3
+ add_action(
4
+ 'rest_api_init',
5
+ function () {
6
+ $controller = new WPCF7_REST_Controller;
7
+ $controller->register_routes();
8
+ },
9
+ 10, 0
10
+ );
11
 
 
 
12
 
13
+ class WPCF7_REST_Controller {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
 
15
+ const namespace = 'contact-form-7/v1';
16
+
17
+ public function register_routes() {
18
+
19
+ register_rest_route( self::namespace,
20
+ '/contact-forms',
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  array(
22
+ array(
23
+ 'methods' => WP_REST_Server::READABLE,
24
+ 'callback' => array( $this, 'get_contact_forms' ),
25
+ 'permission_callback' => function () {
26
+ if ( current_user_can( 'wpcf7_read_contact_forms' ) ) {
27
+ return true;
28
+ } else {
29
+ return new WP_Error( 'wpcf7_forbidden',
30
+ __( "You are not allowed to access contact forms.", 'contact-form-7' ),
31
+ array( 'status' => 403 )
32
+ );
33
+ }
34
+ },
35
+ ),
36
+ array(
37
+ 'methods' => WP_REST_Server::CREATABLE,
38
+ 'callback' => array( $this, 'create_contact_form' ),
39
+ 'permission_callback' => function () {
40
+ if ( current_user_can( 'wpcf7_edit_contact_forms' ) ) {
41
+ return true;
42
+ } else {
43
+ return new WP_Error( 'wpcf7_forbidden',
44
+ __( "You are not allowed to create a contact form.", 'contact-form-7' ),
45
+ array( 'status' => 403 )
46
+ );
47
+ }
48
+ },
49
+ ),
50
+ )
51
+ );
52
+
53
+ register_rest_route( self::namespace,
54
+ '/contact-forms/(?P<id>\d+)',
55
  array(
56
+ 'args' => $this->get_argument_schema(),
57
+ array(
58
+ 'methods' => WP_REST_Server::READABLE,
59
+ 'callback' => array( $this, 'get_contact_form' ),
60
+ 'permission_callback' => function ( WP_REST_Request $request ) {
61
+ $id = (int) $request->get_param( 'id' );
62
+
63
+ if ( current_user_can( 'wpcf7_edit_contact_form', $id ) ) {
64
+ return true;
65
+ } else {
66
+ return new WP_Error( 'wpcf7_forbidden',
67
+ __( "You are not allowed to access the requested contact form.", 'contact-form-7' ),
68
+ array( 'status' => 403 )
69
+ );
70
+ }
71
+ },
72
+ ),
73
+ array(
74
+ 'methods' => WP_REST_Server::EDITABLE,
75
+ 'callback' => array( $this, 'update_contact_form' ),
76
+ 'permission_callback' => function ( WP_REST_Request $request ) {
77
+ $id = (int) $request->get_param( 'id' );
78
+
79
+ if ( current_user_can( 'wpcf7_edit_contact_form', $id ) ) {
80
+ return true;
81
+ } else {
82
+ return new WP_Error( 'wpcf7_forbidden',
83
+ __( "You are not allowed to access the requested contact form.", 'contact-form-7' ),
84
+ array( 'status' => 403 )
85
+ );
86
+ }
87
+ },
88
+ ),
89
+ array(
90
+ 'methods' => WP_REST_Server::DELETABLE,
91
+ 'callback' => array( $this, 'delete_contact_form' ),
92
+ 'permission_callback' => function ( WP_REST_Request $request ) {
93
+ $id = (int) $request->get_param( 'id' );
94
+
95
+ if ( current_user_can( 'wpcf7_delete_contact_form', $id ) ) {
96
+ return true;
97
+ } else {
98
+ return new WP_Error( 'wpcf7_forbidden',
99
+ __( "You are not allowed to access the requested contact form.", 'contact-form-7' ),
100
+ array( 'status' => 403 )
101
+ );
102
+ }
103
+ },
104
+ ),
105
+ )
106
+ );
107
 
108
+ register_rest_route( self::namespace,
109
+ '/contact-forms/(?P<id>\d+)/feedback',
 
110
  array(
111
+ 'args' => $this->get_argument_schema(),
112
+ array(
113
+ 'methods' => WP_REST_Server::CREATABLE,
114
+ 'callback' => array( $this, 'create_feedback' ),
115
+ 'permission_callback' => '__return_true',
116
+ ),
117
+ )
118
+ );
119
 
120
+ register_rest_route( self::namespace,
121
+ '/contact-forms/(?P<id>\d+)/refill',
 
122
  array(
123
+ 'args' => $this->get_argument_schema(),
124
+ array(
125
+ 'methods' => WP_REST_Server::READABLE,
126
+ 'callback' => array( $this, 'get_refill' ),
127
+ 'permission_callback' => '__return_true',
128
+ ),
129
+ )
130
+ );
131
+ }
132
 
133
+ public function get_contact_forms( WP_REST_Request $request ) {
134
+ $args = array();
135
 
136
+ $per_page = $request->get_param( 'per_page' );
137
 
138
+ if ( null !== $per_page ) {
139
+ $args['posts_per_page'] = (int) $per_page;
140
+ }
141
 
142
+ $offset = $request->get_param( 'offset' );
143
 
144
+ if ( null !== $offset ) {
145
+ $args['offset'] = (int) $offset;
146
+ }
147
 
148
+ $order = $request->get_param( 'order' );
149
 
150
+ if ( null !== $order ) {
151
+ $args['order'] = (string) $order;
152
+ }
153
 
154
+ $orderby = $request->get_param( 'orderby' );
155
 
156
+ if ( null !== $orderby ) {
157
+ $args['orderby'] = (string) $orderby;
158
+ }
159
+
160
+ $search = $request->get_param( 'search' );
161
+
162
+ if ( null !== $search ) {
163
+ $args['s'] = (string) $search;
164
+ }
165
 
166
+ $items = WPCF7_ContactForm::find( $args );
167
 
168
+ $response = array();
169
+
170
+ foreach ( $items as $item ) {
171
+ $response[] = array(
172
+ 'id' => $item->id(),
173
+ 'slug' => $item->name(),
174
+ 'title' => $item->title(),
175
+ 'locale' => $item->locale(),
176
+ );
177
+ }
178
+
179
+ return rest_ensure_response( $response );
180
  }
181
 
182
+ public function create_contact_form( WP_REST_Request $request ) {
183
+ $id = (int) $request->get_param( 'id' );
184
 
185
+ if ( $id ) {
186
+ return new WP_Error( 'wpcf7_post_exists',
187
+ __( "Cannot create existing contact form.", 'contact-form-7' ),
188
+ array( 'status' => 400 )
189
+ );
190
+ }
191
 
192
+ $args = $request->get_params();
193
+ $args['id'] = -1; // Create
194
+ $context = $request->get_param( 'context' );
195
+ $item = wpcf7_save_contact_form( $args, $context );
196
+
197
+ if ( ! $item ) {
198
+ return new WP_Error( 'wpcf7_cannot_save',
199
+ __( "There was an error saving the contact form.", 'contact-form-7' ),
200
+ array( 'status' => 500 )
201
+ );
202
+ }
203
+
204
+ $response = array(
205
  'id' => $item->id(),
206
  'slug' => $item->name(),
207
  'title' => $item->title(),
208
  'locale' => $item->locale(),
209
+ 'properties' => $this->get_properties( $item ),
210
+ 'config_errors' => array(),
211
  );
 
212
 
213
+ if ( wpcf7_validate_configuration() ) {
214
+ $config_validator = new WPCF7_ConfigValidator( $item );
215
+ $config_validator->validate();
216
 
217
+ $response['config_errors'] = $config_validator->collect_error_messages();
 
218
 
219
+ if ( 'save' == $context ) {
220
+ $config_validator->save();
221
+ }
222
+ }
223
+
224
+ return rest_ensure_response( $response );
225
  }
226
 
227
+ public function get_contact_form( WP_REST_Request $request ) {
228
+ $id = (int) $request->get_param( 'id' );
229
+ $item = wpcf7_contact_form( $id );
 
230
 
231
+ if ( ! $item ) {
232
+ return new WP_Error( 'wpcf7_not_found',
233
+ __( "The requested contact form was not found.", 'contact-form-7' ),
234
+ array( 'status' => 404 )
235
+ );
236
+ }
237
 
238
+ $response = array(
239
+ 'id' => $item->id(),
240
+ 'slug' => $item->name(),
241
+ 'title' => $item->title(),
242
+ 'locale' => $item->locale(),
243
+ 'properties' => $this->get_properties( $item ),
244
+ );
 
245
 
246
+ return rest_ensure_response( $response );
247
+ }
 
248
 
249
+ public function update_contact_form( WP_REST_Request $request ) {
250
+ $id = (int) $request->get_param( 'id' );
251
+ $item = wpcf7_contact_form( $id );
252
 
253
+ if ( ! $item ) {
254
+ return new WP_Error( 'wpcf7_not_found',
255
+ __( "The requested contact form was not found.", 'contact-form-7' ),
256
+ array( 'status' => 404 )
257
+ );
258
  }
 
259
 
260
+ $args = $request->get_params();
261
+ $context = $request->get_param( 'context' );
262
+ $item = wpcf7_save_contact_form( $args, $context );
263
 
264
+ if ( ! $item ) {
265
+ return new WP_Error( 'wpcf7_cannot_save',
266
+ __( "There was an error saving the contact form.", 'contact-form-7' ),
267
+ array( 'status' => 500 )
268
+ );
269
+ }
270
 
271
+ $response = array(
272
+ 'id' => $item->id(),
273
+ 'slug' => $item->name(),
274
+ 'title' => $item->title(),
275
+ 'locale' => $item->locale(),
276
+ 'properties' => $this->get_properties( $item ),
277
+ 'config_errors' => array(),
278
  );
 
279
 
280
+ if ( wpcf7_validate_configuration() ) {
281
+ $config_validator = new WPCF7_ConfigValidator( $item );
282
+ $config_validator->validate();
 
 
 
 
283
 
284
+ $response['config_errors'] = $config_validator->collect_error_messages();
 
285
 
286
+ if ( 'save' == $context ) {
287
+ $config_validator->save();
288
+ }
289
+ }
290
 
291
+ return rest_ensure_response( $response );
 
 
 
 
292
  }
293
 
294
+ public function delete_contact_form( WP_REST_Request $request ) {
295
+ $id = (int) $request->get_param( 'id' );
296
+ $item = wpcf7_contact_form( $id );
297
 
298
+ if ( ! $item ) {
299
+ return new WP_Error( 'wpcf7_not_found',
300
+ __( "The requested contact form was not found.", 'contact-form-7' ),
301
+ array( 'status' => 404 )
302
+ );
303
+ }
304
 
305
+ $result = $item->delete();
 
 
 
 
 
 
 
306
 
307
+ if ( ! $result ) {
308
+ return new WP_Error( 'wpcf7_cannot_delete',
309
+ __( "There was an error deleting the contact form.", 'contact-form-7' ),
310
+ array( 'status' => 500 )
311
+ );
312
+ }
313
 
314
+ $response = array( 'deleted' => true );
315
 
316
+ return rest_ensure_response( $response );
 
 
317
  }
318
 
319
+ public function create_feedback( WP_REST_Request $request ) {
320
+ $url_params = $request->get_url_params();
321
 
322
+ $item = null;
 
 
323
 
324
+ if ( ! empty( $url_params['id'] ) ) {
325
+ $item = wpcf7_contact_form( $url_params['id'] );
326
+ }
 
 
 
327
 
328
+ if ( ! $item ) {
329
+ return new WP_Error( 'wpcf7_not_found',
330
+ __( "The requested contact form was not found.", 'contact-form-7' ),
331
+ array( 'status' => 404 )
332
+ );
333
+ }
334
 
335
+ $unit_tag = wpcf7_sanitize_unit_tag(
336
+ $request->get_param( '_wpcf7_unit_tag' )
 
 
337
  );
 
338
 
339
+ $result = $item->submit();
340
+
341
+ $response = array_merge( $result, array(
342
+ 'into' => sprintf( '#%s', $unit_tag ),
343
+ 'invalid_fields' => array(),
344
+ ) );
345
+
346
+ if ( ! empty( $result['invalid_fields'] ) ) {
347
+ $invalid_fields = array();
348
+
349
+ foreach ( (array) $result['invalid_fields'] as $name => $field ) {
350
+ $name = sanitize_html_class( $name );
351
+
352
+ $invalid_fields[] = array(
353
+ 'into' => sprintf(
354
+ 'span.wpcf7-form-control-wrap.%s',
355
+ $name
356
+ ),
357
+ 'message' => $field['reason'],
358
+ 'idref' => $field['idref'],
359
+ 'error_id' => sprintf(
360
+ '%1$s-ve-%2$s',
361
+ $unit_tag,
362
+ $name
363
+ ),
364
+ );
365
+ }
366
 
367
+ $response['invalid_fields'] = $invalid_fields;
368
+ }
369
 
370
+ $response = wpcf7_apply_filters_deprecated(
371
+ 'wpcf7_ajax_json_echo',
372
+ array( $response, $result ),
373
+ '5.2',
374
+ 'wpcf7_feedback_response'
375
+ );
376
 
377
+ $response = apply_filters( 'wpcf7_feedback_response', $response, $result );
378
 
379
+ return rest_ensure_response( $response );
 
380
  }
381
 
382
+ public function get_refill( WP_REST_Request $request ) {
383
+ $id = (int) $request->get_param( 'id' );
384
+ $item = wpcf7_contact_form( $id );
 
 
 
385
 
386
+ if ( ! $item ) {
387
+ return new WP_Error( 'wpcf7_not_found',
388
+ __( "The requested contact form was not found.", 'contact-form-7' ),
389
+ array( 'status' => 404 )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
390
  );
391
  }
392
 
393
+ $response = wpcf7_apply_filters_deprecated(
394
+ 'wpcf7_ajax_onload',
395
+ array( array() ),
396
+ '5.2',
397
+ 'wpcf7_refill_response'
398
+ );
 
 
 
 
 
399
 
400
+ $response = apply_filters( 'wpcf7_refill_response', array() );
 
401
 
402
+ return rest_ensure_response( $response );
403
+ }
 
404
 
405
+ private function get_properties( WPCF7_ContactForm $contact_form ) {
406
+ $properties = $contact_form->get_properties();
407
+
408
+ $properties['form'] = array(
409
+ 'content' => (string) $properties['form'],
410
+ 'fields' => array_map(
411
+ function ( WPCF7_FormTag $form_tag ) {
412
+ return array(
413
+ 'type' => $form_tag->type,
414
+ 'basetype' => $form_tag->basetype,
415
+ 'name' => $form_tag->name,
416
+ 'options' => $form_tag->options,
417
+ 'raw_values' => $form_tag->raw_values,
418
+ 'labels' => $form_tag->labels,
419
+ 'values' => $form_tag->values,
420
+ 'pipes' => $form_tag->pipes instanceof WPCF7_Pipes
421
+ ? $form_tag->pipes->to_array()
422
+ : $form_tag->pipes,
423
+ 'content' => $form_tag->content,
424
+ );
425
+ },
426
+ $contact_form->scan_form_tags()
427
+ ),
428
  );
 
429
 
430
+ $properties['additional_settings'] = array(
431
+ 'content' => (string) $properties['additional_settings'],
432
+ 'settings' => array_filter( array_map(
433
+ function ( $setting ) {
434
+ $pattern = '/^([a-zA-Z0-9_]+)[\t ]*:(.*)$/';
 
435
 
436
+ if ( preg_match( $pattern, $setting, $matches ) ) {
437
+ $name = trim( $matches[1] );
438
+ $value = trim( $matches[2] );
439
 
440
+ if ( in_array( $value, array( 'on', 'true' ), true ) ) {
441
+ $value = true;
442
+ } elseif ( in_array( $value, array( 'off', 'false' ), true ) ) {
443
+ $value = false;
444
+ }
445
 
446
+ return array( $name, $value );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
447
  }
448
 
449
+ return false;
450
+ },
451
+ explode( "\n", $properties['additional_settings'] )
452
+ ) ),
453
+ );
454
+
455
+ return $properties;
456
+ }
457
 
458
+ private function get_argument_schema() {
459
+ return array(
460
+ 'id' => array(
461
+ 'description' => __( "Unique identifier for the contact form.", 'contact-form-7' ),
462
+ 'type' => 'integer',
463
+ 'required' => true,
464
+ ),
465
+ );
466
+ }
467
 
 
468
  }
includes/submission.php CHANGED
@@ -17,6 +17,8 @@ class WPCF7_Submission {
17
  private $meta = array();
18
  private $consent = array();
19
  private $spam_log = array();
 
 
20
 
21
  public static function get_instance( $contact_form = null, $args = '' ) {
22
  if ( $contact_form instanceof WPCF7_ContactForm ) {
@@ -36,10 +38,12 @@ class WPCF7_Submission {
36
  }
37
  }
38
 
 
39
  public static function is_restful() {
40
  return defined( 'REST_REQUEST' ) && REST_REQUEST;
41
  }
42
 
 
43
  private function __construct( WPCF7_ContactForm $contact_form, $args = '' ) {
44
  $args = wp_parse_args( $args, array(
45
  'skip_mail' => false,
@@ -49,6 +53,7 @@ class WPCF7_Submission {
49
  $this->skip_mail = (bool) $args['skip_mail'];
50
  }
51
 
 
52
  private function proceed() {
53
  $contact_form = $this->contact_form;
54
 
@@ -108,10 +113,12 @@ class WPCF7_Submission {
108
  $this->remove_uploaded_files();
109
  }
110
 
 
111
  public function get_status() {
112
  return $this->status;
113
  }
114
 
 
115
  public function set_status( $status ) {
116
  if ( preg_match( '/^[a-z][0-9a-z_]+$/', $status ) ) {
117
  $this->status = $status;
@@ -121,23 +128,76 @@ class WPCF7_Submission {
121
  return false;
122
  }
123
 
 
124
  public function is( $status ) {
125
  return $this->status == $status;
126
  }
127
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
  public function get_response() {
129
  return $this->response;
130
  }
131
 
 
132
  public function set_response( $response ) {
133
  $this->response = $response;
134
  return true;
135
  }
136
 
 
137
  public function get_contact_form() {
138
  return $this->contact_form;
139
  }
140
 
 
141
  public function get_invalid_field( $name ) {
142
  if ( isset( $this->invalid_fields[$name] ) ) {
143
  return $this->invalid_fields[$name];
@@ -146,16 +206,19 @@ class WPCF7_Submission {
146
  }
147
  }
148
 
 
149
  public function get_invalid_fields() {
150
  return $this->invalid_fields;
151
  }
152
 
 
153
  public function get_meta( $name ) {
154
  if ( isset( $this->meta[$name] ) ) {
155
  return $this->meta[$name];
156
  }
157
  }
158
 
 
159
  private function setup_meta_data() {
160
  $timestamp = time();
161
 
@@ -170,7 +233,7 @@ class WPCF7_Submission {
170
  $url = $this->get_request_url();
171
 
172
  $unit_tag = isset( $_POST['_wpcf7_unit_tag'] )
173
- ? $_POST['_wpcf7_unit_tag'] : '';
174
 
175
  $container_post_id = isset( $_POST['_wpcf7_container_post'] )
176
  ? (int) $_POST['_wpcf7_container_post'] : 0;
@@ -194,6 +257,7 @@ class WPCF7_Submission {
194
  return $this->meta;
195
  }
196
 
 
197
  public function get_posted_data( $name = '' ) {
198
  if ( ! empty( $name ) ) {
199
  if ( isset( $this->posted_data[$name] ) ) {
@@ -206,6 +270,7 @@ class WPCF7_Submission {
206
  return $this->posted_data;
207
  }
208
 
 
209
  private function setup_posted_data() {
210
  $posted_data = array_filter( (array) $_POST, function( $key ) {
211
  return '_' !== substr( $key, 0, 1 );
@@ -262,7 +327,14 @@ class WPCF7_Submission {
262
  -1, 1
263
  );
264
 
265
- $tied_item = html_entity_decode( $tied_item, ENT_QUOTES, 'UTF-8' );
 
 
 
 
 
 
 
266
 
267
  if ( $last_val === $tied_item ) {
268
  $value[] = sprintf( '%s %s',
@@ -290,21 +362,12 @@ class WPCF7_Submission {
290
 
291
  $this->posted_data = apply_filters( 'wpcf7_posted_data', $posted_data );
292
 
293
- $this->posted_data_hash = wp_hash(
294
- wpcf7_flat_join( array_merge(
295
- array(
296
- $this->get_meta( 'remote_ip' ),
297
- $this->get_meta( 'remote_port' ),
298
- $this->get_meta( 'unit_tag' ),
299
- ),
300
- $this->posted_data
301
- ) ),
302
- 'wpcf7_submission'
303
- );
304
 
305
  return $this->posted_data;
306
  }
307
 
 
308
  private function sanitize_posted_data( $value ) {
309
  if ( is_array( $value ) ) {
310
  $value = array_map( array( $this, 'sanitize_posted_data' ), $value );
@@ -316,10 +379,96 @@ class WPCF7_Submission {
316
  return $value;
317
  }
318
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
319
  public function get_posted_data_hash() {
320
  return $this->posted_data_hash;
321
  }
322
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
323
  private function get_remote_ip_addr() {
324
  $ip_addr = '';
325
 
@@ -331,6 +480,7 @@ class WPCF7_Submission {
331
  return apply_filters( 'wpcf7_remote_ip_addr', $ip_addr );
332
  }
333
 
 
334
  private function get_request_url() {
335
  $home_url = untrailingslashit( home_url() );
336
 
@@ -350,6 +500,7 @@ class WPCF7_Submission {
350
  return $url;
351
  }
352
 
 
353
  private function validate() {
354
  if ( $this->invalid_fields ) {
355
  return false;
@@ -373,19 +524,23 @@ class WPCF7_Submission {
373
  return $result->is_valid();
374
  }
375
 
 
376
  private function accepted() {
377
  return apply_filters( 'wpcf7_acceptance', true, $this );
378
  }
379
 
 
380
  public function add_consent( $name, $conditions ) {
381
  $this->consent[$name] = $conditions;
382
  return true;
383
  }
384
 
 
385
  public function collect_consent() {
386
  return (array) $this->consent;
387
  }
388
 
 
389
  private function spam() {
390
  $spam = false;
391
 
@@ -426,6 +581,7 @@ class WPCF7_Submission {
426
  return apply_filters( 'wpcf7_spam', $spam, $this );
427
  }
428
 
 
429
  public function add_spam_log( $args = '' ) {
430
  $args = wp_parse_args( $args, array(
431
  'agent' => '',
@@ -435,10 +591,12 @@ class WPCF7_Submission {
435
  $this->spam_log[] = $args;
436
  }
437
 
 
438
  public function get_spam_log() {
439
  return $this->spam_log;
440
  }
441
 
 
442
  private function verify_nonce() {
443
  if ( ! $this->contact_form->nonce_is_active() ) {
444
  return true;
@@ -447,6 +605,7 @@ class WPCF7_Submission {
447
  return wpcf7_verify_nonce( $_POST['_wpnonce'] );
448
  }
449
 
 
450
  /* Mail */
451
 
452
  private function before_send_mail() {
@@ -461,6 +620,7 @@ class WPCF7_Submission {
461
  return ! $abort;
462
  }
463
 
 
464
  private function mail() {
465
  $contact_form = $this->contact_form;
466
 
@@ -496,10 +656,12 @@ class WPCF7_Submission {
496
  return false;
497
  }
498
 
 
499
  public function uploaded_files() {
500
  return $this->uploaded_files;
501
  }
502
 
 
503
  private function add_uploaded_file( $name, $file_path ) {
504
  if ( ! wpcf7_is_name( $name ) ) {
505
  return false;
@@ -523,6 +685,7 @@ class WPCF7_Submission {
523
  }
524
  }
525
 
 
526
  private function remove_uploaded_files() {
527
  foreach ( (array) $this->uploaded_files as $file_path ) {
528
  $paths = (array) $file_path;
@@ -540,6 +703,7 @@ class WPCF7_Submission {
540
  }
541
  }
542
 
 
543
  private function unship_uploaded_files() {
544
  $result = new WPCF7_Validation();
545
 
17
  private $meta = array();
18
  private $consent = array();
19
  private $spam_log = array();
20
+ private $result_props = array();
21
+
22
 
23
  public static function get_instance( $contact_form = null, $args = '' ) {
24
  if ( $contact_form instanceof WPCF7_ContactForm ) {
38
  }
39
  }
40
 
41
+
42
  public static function is_restful() {
43
  return defined( 'REST_REQUEST' ) && REST_REQUEST;
44
  }
45
 
46
+
47
  private function __construct( WPCF7_ContactForm $contact_form, $args = '' ) {
48
  $args = wp_parse_args( $args, array(
49
  'skip_mail' => false,
53
  $this->skip_mail = (bool) $args['skip_mail'];
54
  }
55
 
56
+
57
  private function proceed() {
58
  $contact_form = $this->contact_form;
59
 
113
  $this->remove_uploaded_files();
114
  }
115
 
116
+
117
  public function get_status() {
118
  return $this->status;
119
  }
120
 
121
+
122
  public function set_status( $status ) {
123
  if ( preg_match( '/^[a-z][0-9a-z_]+$/', $status ) ) {
124
  $this->status = $status;
128
  return false;
129
  }
130
 
131
+
132
  public function is( $status ) {
133
  return $this->status == $status;
134
  }
135
 
136
+
137
+ /**
138
+ * Returns an associative array of submission result properties.
139
+ *
140
+ * @return array Submission result properties.
141
+ */
142
+ public function get_result() {
143
+ $result = array_merge( $this->result_props, array(
144
+ 'status' => $this->get_status(),
145
+ 'message' => $this->get_response(),
146
+ ) );
147
+
148
+ if ( $this->is( 'validation_failed' ) ) {
149
+ $result['invalid_fields'] = $this->get_invalid_fields();
150
+ }
151
+
152
+ switch ( $this->get_status() ) {
153
+ case 'init':
154
+ case 'validation_failed':
155
+ case 'acceptance_missing':
156
+ case 'spam':
157
+ $result['posted_data_hash'] = '';
158
+ break;
159
+ default:
160
+ $result['posted_data_hash'] = $this->get_posted_data_hash();
161
+ break;
162
+ }
163
+
164
+ $result = apply_filters( 'wpcf7_submission_result', $result, $this );
165
+
166
+ return $result;
167
+ }
168
+
169
+
170
+ /**
171
+ * Adds items to the array of submission result properties.
172
+ *
173
+ * @param string|array|object $args Value to add to result properties.
174
+ * @return array Added result properties.
175
+ */
176
+ public function add_result_props( $args = '' ) {
177
+ $args = wp_parse_args( $args, array() );
178
+
179
+ $this->result_props = array_merge( $this->result_props, $args );
180
+
181
+ return $args;
182
+ }
183
+
184
+
185
  public function get_response() {
186
  return $this->response;
187
  }
188
 
189
+
190
  public function set_response( $response ) {
191
  $this->response = $response;
192
  return true;
193
  }
194
 
195
+
196
  public function get_contact_form() {
197
  return $this->contact_form;
198
  }
199
 
200
+
201
  public function get_invalid_field( $name ) {
202
  if ( isset( $this->invalid_fields[$name] ) ) {
203
  return $this->invalid_fields[$name];
206
  }
207
  }
208
 
209
+
210
  public function get_invalid_fields() {
211
  return $this->invalid_fields;
212
  }
213
 
214
+
215
  public function get_meta( $name ) {
216
  if ( isset( $this->meta[$name] ) ) {
217
  return $this->meta[$name];
218
  }
219
  }
220
 
221
+
222
  private function setup_meta_data() {
223
  $timestamp = time();
224
 
233
  $url = $this->get_request_url();
234
 
235
  $unit_tag = isset( $_POST['_wpcf7_unit_tag'] )
236
+ ? wpcf7_sanitize_unit_tag( $_POST['_wpcf7_unit_tag'] ) : '';
237
 
238
  $container_post_id = isset( $_POST['_wpcf7_container_post'] )
239
  ? (int) $_POST['_wpcf7_container_post'] : 0;
257
  return $this->meta;
258
  }
259
 
260
+
261
  public function get_posted_data( $name = '' ) {
262
  if ( ! empty( $name ) ) {
263
  if ( isset( $this->posted_data[$name] ) ) {
270
  return $this->posted_data;
271
  }
272
 
273
+
274
  private function setup_posted_data() {
275
  $posted_data = array_filter( (array) $_POST, function( $key ) {
276
  return '_' !== substr( $key, 0, 1 );
327
  -1, 1
328
  );
329
 
330
+ list( $last_val, $tied_item ) = array_map(
331
+ function ( $item ) {
332
+ return wpcf7_canonicalize( $item, array(
333
+ 'strto' => 'as-is',
334
+ ) );
335
+ },
336
+ array( $last_val, $tied_item )
337
+ );
338
 
339
  if ( $last_val === $tied_item ) {
340
  $value[] = sprintf( '%s %s',
362
 
363
  $this->posted_data = apply_filters( 'wpcf7_posted_data', $posted_data );
364
 
365
+ $this->posted_data_hash = $this->create_posted_data_hash();
 
 
 
 
 
 
 
 
 
 
366
 
367
  return $this->posted_data;
368
  }
369
 
370
+
371
  private function sanitize_posted_data( $value ) {
372
  if ( is_array( $value ) ) {
373
  $value = array_map( array( $this, 'sanitize_posted_data' ), $value );
379
  return $value;
380
  }
381
 
382
+
383
+ /**
384
+ * Returns the time-dependent variable for hash creation.
385
+ *
386
+ * @return float Float value rounded up to the next highest integer.
387
+ */
388
+ private function posted_data_hash_tick() {
389
+ return ceil( time() / ( HOUR_IN_SECONDS / 2 ) );
390
+ }
391
+
392
+
393
+ /**
394
+ * Creates a hash string based on posted data, the remote IP address,
395
+ * contact form location, and window of time.
396
+ *
397
+ * @param string $tick Optional. If not specified, result of
398
+ * posted_data_hash_tick() will be used.
399
+ * @return string The hash.
400
+ */
401
+ private function create_posted_data_hash( $tick = '' ) {
402
+ if ( '' === $tick ) {
403
+ $tick = $this->posted_data_hash_tick();
404
+ }
405
+
406
+ $hash = wp_hash(
407
+ wpcf7_flat_join( array_merge(
408
+ array(
409
+ $tick,
410
+ $this->get_meta( 'remote_ip' ),
411
+ $this->get_meta( 'unit_tag' ),
412
+ ),
413
+ $this->posted_data
414
+ ) ),
415
+ 'wpcf7_submission'
416
+ );
417
+
418
+ return $hash;
419
+ }
420
+
421
+
422
+ /**
423
+ * Returns the hash string created for this submission.
424
+ *
425
+ * @return string The current hash for the submission.
426
+ */
427
  public function get_posted_data_hash() {
428
  return $this->posted_data_hash;
429
  }
430
 
431
+
432
+ /**
433
+ * Verifies that the given string is equivalent to the posted data hash.
434
+ *
435
+ * @param string $hash Optional. This value will be compared to the
436
+ * current posted data hash for the submission. If not
437
+ * specified, the value of $_POST['_wpcf7_posted_data_hash']
438
+ * will be used.
439
+ * @return int|bool 1 if $hash is created 0-30 minutes ago,
440
+ * 2 if $hash is created 30-60 minutes ago,
441
+ * false if $hash is invalid.
442
+ */
443
+ public function verify_posted_data_hash( $hash = '' ) {
444
+ if ( '' === $hash and ! empty( $_POST['_wpcf7_posted_data_hash'] ) ) {
445
+ $hash = trim( $_POST['_wpcf7_posted_data_hash'] );
446
+ }
447
+
448
+ if ( '' === $hash ) {
449
+ return false;
450
+ }
451
+
452
+ $tick = $this->posted_data_hash_tick();
453
+
454
+ // Hash created 0-30 minutes ago.
455
+ $expected_1 = $this->create_posted_data_hash( $tick );
456
+
457
+ if ( hash_equals( $expected_1, $hash ) ) {
458
+ return 1;
459
+ }
460
+
461
+ // Hash created 30-60 minutes ago.
462
+ $expected_2 = $this->create_posted_data_hash( $tick - 1 );
463
+
464
+ if ( hash_equals( $expected_2, $hash ) ) {
465
+ return 2;
466
+ }
467
+
468
+ return false;
469
+ }
470
+
471
+
472
  private function get_remote_ip_addr() {
473
  $ip_addr = '';
474
 
480
  return apply_filters( 'wpcf7_remote_ip_addr', $ip_addr );
481
  }
482
 
483
+
484
  private function get_request_url() {
485
  $home_url = untrailingslashit( home_url() );
486
 
500
  return $url;
501
  }
502
 
503
+
504
  private function validate() {
505
  if ( $this->invalid_fields ) {
506
  return false;
524
  return $result->is_valid();
525
  }
526
 
527
+
528
  private function accepted() {
529
  return apply_filters( 'wpcf7_acceptance', true, $this );
530
  }
531
 
532
+
533
  public function add_consent( $name, $conditions ) {
534
  $this->consent[$name] = $conditions;
535
  return true;
536
  }
537
 
538
+
539
  public function collect_consent() {
540
  return (array) $this->consent;
541
  }
542
 
543
+
544
  private function spam() {
545
  $spam = false;
546
 
581
  return apply_filters( 'wpcf7_spam', $spam, $this );
582
  }
583
 
584
+
585
  public function add_spam_log( $args = '' ) {
586
  $args = wp_parse_args( $args, array(
587
  'agent' => '',
591
  $this->spam_log[] = $args;
592
  }
593
 
594
+
595
  public function get_spam_log() {
596
  return $this->spam_log;
597
  }
598
 
599
+
600
  private function verify_nonce() {
601
  if ( ! $this->contact_form->nonce_is_active() ) {
602
  return true;
605
  return wpcf7_verify_nonce( $_POST['_wpnonce'] );
606
  }
607
 
608
+
609
  /* Mail */
610
 
611
  private function before_send_mail() {
620
  return ! $abort;
621
  }
622
 
623
+
624
  private function mail() {
625
  $contact_form = $this->contact_form;
626
 
656
  return false;
657
  }
658
 
659
+
660
  public function uploaded_files() {
661
  return $this->uploaded_files;
662
  }
663
 
664
+
665
  private function add_uploaded_file( $name, $file_path ) {
666
  if ( ! wpcf7_is_name( $name ) ) {
667
  return false;
685
  }
686
  }
687
 
688
+
689
  private function remove_uploaded_files() {
690
  foreach ( (array) $this->uploaded_files as $file_path ) {
691
  $paths = (array) $file_path;
703
  }
704
  }
705
 
706
+
707
  private function unship_uploaded_files() {
708
  $result = new WPCF7_Validation();
709
 
includes/validation-functions.php CHANGED
@@ -54,13 +54,18 @@ function wpcf7_is_date( $date ) {
54
  function wpcf7_is_mailbox_list( $mailbox_list ) {
55
  if ( ! is_array( $mailbox_list ) ) {
56
  $mailbox_text = (string) $mailbox_list;
57
- $mailbox_text = wp_unslash( $mailbox_text );
58
 
59
- $mailbox_text = preg_replace( '/\\\\(?:\"|\')/', 'esc-quote',
60
- $mailbox_text );
 
 
 
61
 
62
- $mailbox_text = preg_replace( '/(?:\".*?\"|\'.*?\')/', 'quoted-string',
63
- $mailbox_text );
 
 
 
64
 
65
  $mailbox_list = explode( ',', $mailbox_text );
66
  }
@@ -74,6 +79,10 @@ function wpcf7_is_mailbox_list( $mailbox_list ) {
74
 
75
  $mailbox = trim( $mailbox );
76
 
 
 
 
 
77
  if ( preg_match( '/<(.+)>$/', $mailbox, $matches ) ) {
78
  $addr_spec = $matches[1];
79
  } else {
@@ -154,13 +163,30 @@ function wpcf7_is_email_in_site_domain( $email ) {
154
  return false;
155
  }
156
 
 
 
 
 
 
 
 
 
 
 
 
157
  function wpcf7_is_file_path_in_content_dir( $path ) {
158
- if ( 0 === strpos( realpath( $path ), realpath( WP_CONTENT_DIR ) ) ) {
 
 
 
 
 
 
159
  return true;
160
  }
161
 
162
  if ( defined( 'UPLOADS' )
163
- and 0 === strpos( realpath( $path ), realpath( ABSPATH . UPLOADS ) ) ) {
164
  return true;
165
  }
166
 
54
  function wpcf7_is_mailbox_list( $mailbox_list ) {
55
  if ( ! is_array( $mailbox_list ) ) {
56
  $mailbox_text = (string) $mailbox_list;
 
57
 
58
+ $mailbox_text = preg_replace(
59
+ '/\\\\(?:\"|\')/',
60
+ 'esc-quote',
61
+ $mailbox_text
62
+ );
63
 
64
+ $mailbox_text = preg_replace(
65
+ '/(?:\".*?\"|\'.*?\')/',
66
+ 'quoted-string',
67
+ $mailbox_text
68
+ );
69
 
70
  $mailbox_list = explode( ',', $mailbox_text );
71
  }
79
 
80
  $mailbox = trim( $mailbox );
81
 
82
+ if ( '' === $mailbox ) {
83
+ continue;
84
+ }
85
+
86
  if ( preg_match( '/<(.+)>$/', $mailbox, $matches ) ) {
87
  $addr_spec = $matches[1];
88
  } else {
163
  return false;
164
  }
165
 
166
+
167
+ /**
168
+ * Verifies that a given file path is under the directories that WordPress
169
+ * manages for user contents.
170
+ *
171
+ * Returns false if the file at the given path doesn't exist yet.
172
+ *
173
+ * @param string $path A file path.
174
+ * @return bool True if the path is under the content directories,
175
+ * false otherwise.
176
+ */
177
  function wpcf7_is_file_path_in_content_dir( $path ) {
178
+ if ( $real_path = realpath( $path ) ) {
179
+ $path = $real_path;
180
+ } else {
181
+ return false;
182
+ }
183
+
184
+ if ( 0 === strpos( $path, realpath( WP_CONTENT_DIR ) ) ) {
185
  return true;
186
  }
187
 
188
  if ( defined( 'UPLOADS' )
189
+ and 0 === strpos( $path, realpath( ABSPATH . UPLOADS ) ) ) {
190
  return true;
191
  }
192
 
load.php CHANGED
@@ -29,8 +29,12 @@ if ( is_admin() ) {
29
  require_once WPCF7_PLUGIN_DIR . '/includes/controller.php';
30
  }
31
 
 
32
  class WPCF7 {
33
 
 
 
 
34
  public static function load_modules() {
35
  self::load_module( 'acceptance' );
36
  self::load_module( 'akismet' );
@@ -50,11 +54,19 @@ class WPCF7 {
50
  self::load_module( 'response' );
51
  self::load_module( 'select' );
52
  self::load_module( 'sendinblue' );
 
53
  self::load_module( 'submit' );
54
  self::load_module( 'text' );
55
  self::load_module( 'textarea' );
56
  }
57
 
 
 
 
 
 
 
 
58
  protected static function load_module( $mod ) {
59
  $dir = WPCF7_PLUGIN_MODULES_DIR;
60
 
@@ -77,6 +89,16 @@ class WPCF7 {
77
  return false;
78
  }
79
 
 
 
 
 
 
 
 
 
 
 
80
  public static function get_option( $name, $default = false ) {
81
  $option = get_option( 'wpcf7' );
82
 
@@ -91,6 +113,13 @@ class WPCF7 {
91
  }
92
  }
93
 
 
 
 
 
 
 
 
94
  public static function update_option( $name, $value ) {
95
  $option = get_option( 'wpcf7' );
96
  $option = ( false === $option ) ? array() : (array) $option;
@@ -99,18 +128,25 @@ class WPCF7 {
99
  }
100
  }
101
 
 
102
  add_action( 'plugins_loaded', 'wpcf7', 10, 0 );
103
 
 
 
 
104
  function wpcf7() {
105
  WPCF7::load_modules();
106
 
107
- /* Shortcodes */
108
  add_shortcode( 'contact-form-7', 'wpcf7_contact_form_tag_func' );
109
  add_shortcode( 'contact-form', 'wpcf7_contact_form_tag_func' );
110
  }
111
 
 
112
  add_action( 'init', 'wpcf7_init', 10, 0 );
113
 
 
 
 
114
  function wpcf7_init() {
115
  wpcf7_get_request_uri();
116
  wpcf7_register_post_types();
@@ -118,8 +154,12 @@ function wpcf7_init() {
118
  do_action( 'wpcf7_init' );
119
  }
120
 
 
121
  add_action( 'admin_init', 'wpcf7_upgrade', 10, 0 );
122
 
 
 
 
123
  function wpcf7_upgrade() {
124
  $old_ver = WPCF7::get_option( 'version', '0' );
125
  $new_ver = WPCF7_VERSION;
@@ -133,10 +173,13 @@ function wpcf7_upgrade() {
133
  WPCF7::update_option( 'version', $new_ver );
134
  }
135
 
136
- /* Install and default settings */
137
 
138
  add_action( 'activate_' . WPCF7_PLUGIN_BASENAME, 'wpcf7_install', 10, 0 );
139
 
 
 
 
 
140
  function wpcf7_install() {
141
  if ( $opt = get_option( 'wpcf7' ) ) {
142
  return;
29
  require_once WPCF7_PLUGIN_DIR . '/includes/controller.php';
30
  }
31
 
32
+
33
  class WPCF7 {
34
 
35
+ /**
36
+ * Loads modules from the modules directory.
37
+ */
38
  public static function load_modules() {
39
  self::load_module( 'acceptance' );
40
  self::load_module( 'akismet' );
54
  self::load_module( 'response' );
55
  self::load_module( 'select' );
56
  self::load_module( 'sendinblue' );
57
+ self::load_module( 'stripe' );
58
  self::load_module( 'submit' );
59
  self::load_module( 'text' );
60
  self::load_module( 'textarea' );
61
  }
62
 
63
+
64
+ /**
65
+ * Loads the specified module.
66
+ *
67
+ * @param string $mod Name of module.
68
+ * @return bool True on success, false on failure.
69
+ */
70
  protected static function load_module( $mod ) {
71
  $dir = WPCF7_PLUGIN_MODULES_DIR;
72
 
89
  return false;
90
  }
91
 
92
+
93
+ /**
94
+ * Retrieves a named entry from the option array of Contact Form 7.
95
+ *
96
+ * @param string $name Array item key.
97
+ * @param mixed $default Optional. Default value to return if the entry
98
+ * does not exist. Default false.
99
+ * @return mixed Array value tied to the $name key. If nothing found,
100
+ * the $default value will be returned.
101
+ */
102
  public static function get_option( $name, $default = false ) {
103
  $option = get_option( 'wpcf7' );
104
 
113
  }
114
  }
115
 
116
+
117
+ /**
118
+ * Update an entry value on the option array of Contact Form 7.
119
+ *
120
+ * @param string $name Array item key.
121
+ * @param mixed $value Option value.
122
+ */
123
  public static function update_option( $name, $value ) {
124
  $option = get_option( 'wpcf7' );
125
  $option = ( false === $option ) ? array() : (array) $option;
128
  }
129
  }
130
 
131
+
132
  add_action( 'plugins_loaded', 'wpcf7', 10, 0 );
133
 
134
+ /**
135
+ * Loads modules and registers WordPress shortcodes.
136
+ */
137
  function wpcf7() {
138
  WPCF7::load_modules();
139
 
 
140
  add_shortcode( 'contact-form-7', 'wpcf7_contact_form_tag_func' );
141
  add_shortcode( 'contact-form', 'wpcf7_contact_form_tag_func' );
142
  }
143
 
144
+
145
  add_action( 'init', 'wpcf7_init', 10, 0 );
146
 
147
+ /**
148
+ * Registers post types for contact forms.
149
+ */
150
  function wpcf7_init() {
151
  wpcf7_get_request_uri();
152
  wpcf7_register_post_types();
154
  do_action( 'wpcf7_init' );
155
  }
156
 
157
+
158
  add_action( 'admin_init', 'wpcf7_upgrade', 10, 0 );
159
 
160
+ /**
161
+ * Upgrades option data when necessary.
162
+ */
163
  function wpcf7_upgrade() {
164
  $old_ver = WPCF7::get_option( 'version', '0' );
165
  $new_ver = WPCF7_VERSION;
173
  WPCF7::update_option( 'version', $new_ver );
174
  }
175
 
 
176
 
177
  add_action( 'activate_' . WPCF7_PLUGIN_BASENAME, 'wpcf7_install', 10, 0 );
178
 
179
+ /**
180
+ * Callback tied to plugin activation action hook. Attempts to create
181
+ * initial user dataset.
182
+ */
183
  function wpcf7_install() {
184
  if ( $opt = get_option( 'wpcf7' ) ) {
185
  return;
modules/akismet.php CHANGED
@@ -54,6 +54,8 @@ function wpcf7_akismet( $spam, $submission ) {
54
  }
55
  }
56
 
 
 
57
  if ( wpcf7_akismet_comment_check( $c ) ) {
58
  $spam = true;
59
 
@@ -106,7 +108,8 @@ function wpcf7_akismet_submitted_params() {
106
  $tag = $tags[0];
107
 
108
  $akismet = $tag->get_option( 'akismet',
109
- '(author|author_email|author_url)', true );
 
110
 
111
  if ( $akismet ) {
112
  $has_akismet_option = true;
54
  }
55
  }
56
 
57
+ $c = apply_filters( 'wpcf7_akismet_parameters', $c );
58
+
59
  if ( wpcf7_akismet_comment_check( $c ) ) {
60
  $spam = true;
61
 
108
  $tag = $tags[0];
109
 
110
  $akismet = $tag->get_option( 'akismet',
111
+ '(author|author_email|author_url)', true
112
+ );
113
 
114
  if ( $akismet ) {
115
  $has_akismet_option = true;
modules/checkbox.php CHANGED
@@ -157,8 +157,7 @@ function wpcf7_checkbox_form_tag_handler( $tag ) {
157
 
158
  if ( wpcf7_is_posted()
159
  and isset( $_POST[$free_text_name] ) ) {
160
- $free_text_atts['value'] = wp_unslash(
161
- $_POST[$free_text_name] );
162
  }
163
 
164
  $free_text_atts = wpcf7_format_atts( $free_text_atts );
157
 
158
  if ( wpcf7_is_posted()
159
  and isset( $_POST[$free_text_name] ) ) {
160
+ $free_text_atts['value'] = wp_unslash( $_POST[$free_text_name] );
 
161
  }
162
 
163
  $free_text_atts = wpcf7_format_atts( $free_text_atts );
modules/constant-contact.php CHANGED
@@ -1,6 +1,10 @@
1
  <?php
2
 
3
- add_action( 'wpcf7_init', 'wpcf7_constant_contact_register_service', 20, 0 );
 
 
 
 
4
 
5
  function wpcf7_constant_contact_register_service() {
6
  $integration = WPCF7_Integration::get_instance();
@@ -12,8 +16,12 @@ function wpcf7_constant_contact_register_service() {
12
  $integration->add_service( 'constant_contact', $service );
13
  }
14
 
15
- add_action( 'wpcf7_save_contact_form',
16
- 'wpcf7_constant_contact_save_contact_form', 10, 1 );
 
 
 
 
17
 
18
  function wpcf7_constant_contact_save_contact_form( $contact_form ) {
19
  $service = WPCF7_ConstantContact::get_instance();
@@ -56,6 +64,7 @@ function wpcf7_constant_contact_save_contact_form( $contact_form ) {
56
  $service->update_contact_lists( array( $key => $list_names ) );
57
  }
58
 
 
59
  add_action( 'wpcf7_submit', 'wpcf7_constant_contact_submit', 10, 2 );
60
 
61
  function wpcf7_constant_contact_submit( $contact_form, $result ) {
@@ -135,6 +144,7 @@ function wpcf7_constant_contact_submit( $contact_form, $result ) {
135
  $service->create_contact( $request_builder->to_array() );
136
  }
137
 
 
138
  if ( ! class_exists( 'WPCF7_Service_OAuth2' ) ) {
139
  return;
140
  }
@@ -941,7 +951,7 @@ class WPCF7_ConstantContact_ContactPostRequest {
941
  }
942
 
943
  protected function strlen( $string ) {
944
- return wpcf7_count_code_units( stripslashes( $string ) );
945
  }
946
 
947
  }
1
  <?php
2
 
3
+ add_action(
4
+ 'wpcf7_init',
5
+ 'wpcf7_constant_contact_register_service',
6
+ 5, 0
7
+ );
8
 
9
  function wpcf7_constant_contact_register_service() {
10
  $integration = WPCF7_Integration::get_instance();
16
  $integration->add_service( 'constant_contact', $service );
17
  }
18
 
19
+
20
+ add_action(
21
+ 'wpcf7_save_contact_form',
22
+ 'wpcf7_constant_contact_save_contact_form',
23
+ 10, 1
24
+ );
25
 
26
  function wpcf7_constant_contact_save_contact_form( $contact_form ) {
27
  $service = WPCF7_ConstantContact::get_instance();
64
  $service->update_contact_lists( array( $key => $list_names ) );
65
  }
66
 
67
+
68
  add_action( 'wpcf7_submit', 'wpcf7_constant_contact_submit', 10, 2 );
69
 
70
  function wpcf7_constant_contact_submit( $contact_form, $result ) {
144
  $service->create_contact( $request_builder->to_array() );
145
  }
146
 
147
+
148
  if ( ! class_exists( 'WPCF7_Service_OAuth2' ) ) {
149
  return;
150
  }
951
  }
952
 
953
  protected function strlen( $string ) {
954
+ return wpcf7_count_code_units( $string );
955
  }
956
 
957
  }
modules/disallowed-list.php CHANGED
@@ -49,7 +49,13 @@ function wpcf7_disallowed_list( $spam, $submission ) {
49
  }
50
 
51
  function wpcf7_check_disallowed_list( $target ) {
52
- $mod_keys = trim( get_option( 'disallowed_keys' ) );
 
 
 
 
 
 
53
 
54
  if ( '' === $mod_keys ) {
55
  return false;
49
  }
50
 
51
  function wpcf7_check_disallowed_list( $target ) {
52
+ $mod_keys = get_option( 'disallowed_keys' );
53
+
54
+ if ( is_scalar( $mod_keys ) ) {
55
+ $mod_keys = trim( $mod_keys );
56
+ } else {
57
+ $mod_keys = '';
58
+ }
59
 
60
  if ( '' === $mod_keys ) {
61
  return false;
modules/flamingo.php CHANGED
@@ -17,7 +17,8 @@ function wpcf7_flamingo_submit( $contact_form, $result ) {
17
  }
18
 
19
  $cases = (array) apply_filters( 'wpcf7_flamingo_submit_if',
20
- array( 'spam', 'mail_sent', 'mail_failed' ) );
 
21
 
22
  if ( empty( $result['status'] )
23
  or ! in_array( $result['status'], $cases ) ) {
@@ -87,7 +88,9 @@ function wpcf7_flamingo_submit( $contact_form, $result ) {
87
  $channel_id = isset( $post_meta['channel'] )
88
  ? (int) $post_meta['channel']
89
  : wpcf7_flamingo_add_channel(
90
- $contact_form->name(), $contact_form->title() );
 
 
91
 
92
  if ( $channel_id ) {
93
  if ( ! isset( $post_meta['channel'] )
@@ -101,7 +104,8 @@ function wpcf7_flamingo_submit( $contact_form, $result ) {
101
  }
102
 
103
  $channel = get_term( $channel_id,
104
- Flamingo_Inbound_Message::channel_taxonomy );
 
105
 
106
  if ( ! $channel or is_wp_error( $channel ) ) {
107
  $channel = 'contact-form-7';
@@ -136,6 +140,8 @@ function wpcf7_flamingo_submit( $contact_form, $result ) {
136
  $args['recaptcha'] = $submission->recaptcha;
137
  }
138
 
 
 
139
  $flamingo_inbound = Flamingo_Inbound_Message::add( $args );
140
 
141
  if ( empty( $flamingo_contact ) ) {
@@ -195,12 +201,14 @@ function wpcf7_flamingo_add_channel( $slug, $name = '' ) {
195
  }
196
 
197
  $parent = term_exists( 'contact-form-7',
198
- Flamingo_Inbound_Message::channel_taxonomy );
 
199
 
200
  if ( ! $parent ) {
201
  $parent = wp_insert_term( __( 'Contact Form 7', 'contact-form-7' ),
202
  Flamingo_Inbound_Message::channel_taxonomy,
203
- array( 'slug' => 'contact-form-7' ) );
 
204
 
205
  if ( is_wp_error( $parent ) ) {
206
  return false;
@@ -220,12 +228,14 @@ function wpcf7_flamingo_add_channel( $slug, $name = '' ) {
220
 
221
  $channel = term_exists( $slug,
222
  Flamingo_Inbound_Message::channel_taxonomy,
223
- $parent );
 
224
 
225
  if ( ! $channel ) {
226
  $channel = wp_insert_term( $name,
227
  Flamingo_Inbound_Message::channel_taxonomy,
228
- array( 'slug' => $slug, 'parent' => $parent ) );
 
229
 
230
  if ( is_wp_error( $channel ) ) {
231
  return false;
@@ -246,9 +256,11 @@ function wpcf7_flamingo_update_channel( $contact_form ) {
246
 
247
  $channel = isset( $post_meta['channel'] )
248
  ? get_term( $post_meta['channel'],
249
- Flamingo_Inbound_Message::channel_taxonomy )
 
250
  : get_term_by( 'slug', $contact_form->name(),
251
- Flamingo_Inbound_Message::channel_taxonomy );
 
252
 
253
  if ( ! $channel or is_wp_error( $channel ) ) {
254
  return;
@@ -305,11 +317,13 @@ function wpcf7_flamingo_serial_number( $output, $name, $html, $mail_tag = null )
305
  $channel_id = isset( $post_meta['channel'] )
306
  ? (int) $post_meta['channel']
307
  : wpcf7_flamingo_add_channel(
308
- $contact_form->name(), $contact_form->title() );
 
309
 
310
  if ( $channel_id ) {
311
  return 1 + (int) Flamingo_Inbound_Message::count(
312
- array( 'channel_id' => $channel_id ) );
 
313
  }
314
 
315
  return 0;
17
  }
18
 
19
  $cases = (array) apply_filters( 'wpcf7_flamingo_submit_if',
20
+ array( 'spam', 'mail_sent', 'mail_failed' )
21
+ );
22
 
23
  if ( empty( $result['status'] )
24
  or ! in_array( $result['status'], $cases ) ) {
88
  $channel_id = isset( $post_meta['channel'] )
89
  ? (int) $post_meta['channel']
90
  : wpcf7_flamingo_add_channel(
91
+ $contact_form->name(),
92
+ $contact_form->title()
93
+ );
94
 
95
  if ( $channel_id ) {
96
  if ( ! isset( $post_meta['channel'] )
104
  }
105
 
106
  $channel = get_term( $channel_id,
107
+ Flamingo_Inbound_Message::channel_taxonomy
108
+ );
109
 
110
  if ( ! $channel or is_wp_error( $channel ) ) {
111
  $channel = 'contact-form-7';
140
  $args['recaptcha'] = $submission->recaptcha;
141
  }
142
 
143
+ $args = apply_filters( 'wpcf7_flamingo_inbound_message_parameters', $args );
144
+
145
  $flamingo_inbound = Flamingo_Inbound_Message::add( $args );
146
 
147
  if ( empty( $flamingo_contact ) ) {
201
  }
202
 
203
  $parent = term_exists( 'contact-form-7',
204
+ Flamingo_Inbound_Message::channel_taxonomy
205
+ );
206
 
207
  if ( ! $parent ) {
208
  $parent = wp_insert_term( __( 'Contact Form 7', 'contact-form-7' ),
209
  Flamingo_Inbound_Message::channel_taxonomy,
210
+ array( 'slug' => 'contact-form-7' )
211
+ );
212
 
213
  if ( is_wp_error( $parent ) ) {
214
  return false;
228
 
229
  $channel = term_exists( $slug,
230
  Flamingo_Inbound_Message::channel_taxonomy,
231
+ $parent
232
+ );
233
 
234
  if ( ! $channel ) {
235
  $channel = wp_insert_term( $name,
236
  Flamingo_Inbound_Message::channel_taxonomy,
237
+ array( 'slug' => $slug, 'parent' => $parent )
238
+ );
239
 
240
  if ( is_wp_error( $channel ) ) {
241
  return false;
256
 
257
  $channel = isset( $post_meta['channel'] )
258
  ? get_term( $post_meta['channel'],
259
+ Flamingo_Inbound_Message::channel_taxonomy
260
+ )
261
  : get_term_by( 'slug', $contact_form->name(),
262
+ Flamingo_Inbound_Message::channel_taxonomy
263
+ );
264
 
265
  if ( ! $channel or is_wp_error( $channel ) ) {
266
  return;
317
  $channel_id = isset( $post_meta['channel'] )
318
  ? (int) $post_meta['channel']
319
  : wpcf7_flamingo_add_channel(
320
+ $contact_form->name(), $contact_form->title()
321
+ );
322
 
323
  if ( $channel_id ) {
324
  return 1 + (int) Flamingo_Inbound_Message::count(
325
+ array( 'channel_id' => $channel_id )
326
+ );
327
  }
328
 
329
  return 0;
modules/quiz.php CHANGED
@@ -70,7 +70,9 @@ function wpcf7_quiz_form_tag_handler( $tag ) {
70
  $answer = '2';
71
  }
72
 
73
- $answer = wpcf7_canonicalize( $answer );
 
 
74
 
75
  $atts['type'] = 'text';
76
  $atts['name'] = $tag->name;
@@ -95,8 +97,11 @@ add_filter( 'wpcf7_validate_quiz', 'wpcf7_quiz_validation_filter', 10, 2 );
95
  function wpcf7_quiz_validation_filter( $result, $tag ) {
96
  $name = $tag->name;
97
 
98
- $answer = isset( $_POST[$name] ) ? wpcf7_canonicalize( $_POST[$name] ) : '';
99
- $answer = wp_unslash( $answer );
 
 
 
100
 
101
  $answer_hash = wp_hash( $answer, 'wpcf7_quiz' );
102
 
@@ -149,7 +154,9 @@ function wpcf7_quiz_ajax_refill( $items ) {
149
  $answer = '2';
150
  }
151
 
152
- $answer = wpcf7_canonicalize( $answer );
 
 
153
 
154
  $refill[$name] = array( $question, wp_hash( $answer, 'wpcf7_quiz' ) );
155
  }
70
  $answer = '2';
71
  }
72
 
73
+ $answer = wpcf7_canonicalize( $answer, array(
74
+ 'strip_separators' => true,
75
+ ) );
76
 
77
  $atts['type'] = 'text';
78
  $atts['name'] = $tag->name;
97
  function wpcf7_quiz_validation_filter( $result, $tag ) {
98
  $name = $tag->name;
99
 
100
+ $answer = isset( $_POST[$name] ) ? wp_unslash( $_POST[$name] ) : '';
101
+
102
+ $answer = wpcf7_canonicalize( $answer, array(
103
+ 'strip_separators' => true,
104
+ ) );
105
 
106
  $answer_hash = wp_hash( $answer, 'wpcf7_quiz' );
107
 
154
  $answer = '2';
155
  }
156
 
157
+ $answer = wpcf7_canonicalize( $answer, array(
158
+ 'strip_separators' => true,
159
+ ) );
160
 
161
  $refill[$name] = array( $question, wp_hash( $answer, 'wpcf7_quiz' ) );
162
  }
modules/really-simple-captcha.php CHANGED
@@ -432,14 +432,28 @@ function wpcf7_init_captcha() {
432
  return $captcha;
433
  }
434
 
 
 
 
 
 
 
435
  function wpcf7_captcha_tmp_dir() {
436
  if ( defined( 'WPCF7_CAPTCHA_TMP_DIR' ) ) {
437
- return WPCF7_CAPTCHA_TMP_DIR;
438
- } else {
439
- return path_join( wpcf7_upload_dir( 'dir' ), 'wpcf7_captcha' );
 
 
 
440
  }
 
 
 
 
441
  }
442
 
 
443
  function wpcf7_captcha_tmp_url() {
444
  if ( defined( 'WPCF7_CAPTCHA_TMP_URL' ) ) {
445
  return WPCF7_CAPTCHA_TMP_URL;
432
  return $captcha;
433
  }
434
 
435
+
436
+ /**
437
+ * Returns the directory path for Really Simple CAPTCHA files.
438
+ *
439
+ * @return string Directory path.
440
+ */
441
  function wpcf7_captcha_tmp_dir() {
442
  if ( defined( 'WPCF7_CAPTCHA_TMP_DIR' ) ) {
443
+ $dir = path_join( WP_CONTENT_DIR, WPCF7_CAPTCHA_TMP_DIR );
444
+ wp_mkdir_p( $dir );
445
+
446
+ if ( wpcf7_is_file_path_in_content_dir( $dir ) ) {
447
+ return $dir;
448
+ }
449
  }
450
+
451
+ $dir = path_join( wpcf7_upload_dir( 'dir' ), 'wpcf7_captcha' );
452
+ wp_mkdir_p( $dir );
453
+ return $dir;
454
  }
455
 
456
+
457
  function wpcf7_captcha_tmp_url() {
458
  if ( defined( 'WPCF7_CAPTCHA_TMP_URL' ) ) {
459
  return WPCF7_CAPTCHA_TMP_URL;
modules/recaptcha/index.js CHANGED
@@ -1 +1 @@
1
- !function(e){var t={};function n(c){if(t[c])return t[c].exports;var o=t[c]={i:c,l:!1,exports:{}};return e[c].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,c){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:c})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var c=Object.create(null);if(n.r(c),Object.defineProperty(c,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(c,o,function(t){return e[t]}.bind(null,o));return c},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t){document.addEventListener("DOMContentLoaded",e=>{var t;wpcf7_recaptcha={...null!==(t=wpcf7_recaptcha)&&void 0!==t?t:{}};const n=wpcf7_recaptcha.sitekey,{homepage:c,contactform:o}=wpcf7_recaptcha.actions,r=e=>{const{action:t,func:c,params:o}=e;grecaptcha.execute(n,{action:t}).then(e=>{const n=new CustomEvent("wpcf7grecaptchaexecuted",{detail:{action:t,token:e}});document.dispatchEvent(n)}).then(()=>{"function"==typeof c&&c(...o)}).catch(e=>console.error(e))};if(grecaptcha.ready(()=>{r({action:c})}),document.addEventListener("change",e=>{r({action:o})}),"undefined"!=typeof wpcf7&&"function"==typeof wpcf7.submit){const e=wpcf7.submit;wpcf7.submit=(t,n={})=>{r({action:o,func:e,params:[t,n]})}}document.addEventListener("wpcf7grecaptchaexecuted",e=>{const t=document.querySelectorAll('form.wpcf7-form input[name="_wpcf7_recaptcha_response"]');for(let n=0;n<t.length;n++)t[n].setAttribute("value",e.detail.token)})})}]);
1
+ document.addEventListener("DOMContentLoaded",(e=>{var t;wpcf7_recaptcha={...null!==(t=wpcf7_recaptcha)&&void 0!==t?t:{}};const c=wpcf7_recaptcha.sitekey,{homepage:n,contactform:a}=wpcf7_recaptcha.actions,o=e=>{const{action:t,func:n,params:a}=e;grecaptcha.execute(c,{action:t}).then((e=>{const c=new CustomEvent("wpcf7grecaptchaexecuted",{detail:{action:t,token:e}});document.dispatchEvent(c)})).then((()=>{"function"==typeof n&&n(...a)})).catch((e=>console.error(e)))};if(grecaptcha.ready((()=>{o({action:n})})),document.addEventListener("change",(e=>{o({action:a})})),"undefined"!=typeof wpcf7&&"function"==typeof wpcf7.submit){const e=wpcf7.submit;wpcf7.submit=(t,c={})=>{o({action:a,func:e,params:[t,c]})}}document.addEventListener("wpcf7grecaptchaexecuted",(e=>{const t=document.querySelectorAll('form.wpcf7-form input[name="_wpcf7_recaptcha_response"]');for(let c=0;c<t.length;c++)t[c].setAttribute("value",e.detail.token)}))}));
modules/recaptcha/recaptcha.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- add_action( 'wpcf7_init', 'wpcf7_recaptcha_register_service', 10, 0 );
4
 
5
  function wpcf7_recaptcha_register_service() {
6
  $integration = WPCF7_Integration::get_instance();
@@ -23,12 +23,18 @@ function wpcf7_recaptcha_enqueue_scripts() {
23
  return;
24
  }
25
 
 
 
 
 
 
 
26
  wp_enqueue_script( 'google-recaptcha',
27
  add_query_arg(
28
  array(
29
  'render' => $service->get_sitekey(),
30
  ),
31
- 'https://www.google.com/recaptcha/api.js'
32
  ),
33
  array(),
34
  '3.0',
1
  <?php
2
 
3
+ add_action( 'wpcf7_init', 'wpcf7_recaptcha_register_service', 15, 0 );
4
 
5
  function wpcf7_recaptcha_register_service() {
6
  $integration = WPCF7_Integration::get_instance();
23
  return;
24
  }
25
 
26
+ $url = 'https://www.google.com/recaptcha/api.js';
27
+
28
+ if ( apply_filters( 'wpcf7_use_recaptcha_net', false ) ) {
29
+ $url = 'https://www.recaptcha.net/recaptcha/api.js';
30
+ }
31
+
32
  wp_enqueue_script( 'google-recaptcha',
33
  add_query_arg(
34
  array(
35
  'render' => $service->get_sitekey(),
36
  ),
37
+ $url
38
  ),
39
  array(),
40
  '3.0',
modules/sendinblue/sendinblue.php CHANGED
@@ -80,11 +80,17 @@ function wpcf7_sendinblue_submit( $contact_form, $result ) {
80
  return;
81
  }
82
 
83
- $contact_id = $service->create_contact( array(
84
- 'email' => $attributes['EMAIL'],
85
- 'attributes' => (object) $attributes,
86
- 'listIds' => (array) $prop['contact_lists'],
87
- ) );
 
 
 
 
 
 
88
 
89
  if ( ! $contact_id ) {
90
  return;
@@ -94,21 +100,41 @@ function wpcf7_sendinblue_submit( $contact_form, $result ) {
94
  return;
95
  }
96
 
97
- $service->send_email( array(
98
- 'templateId' => absint( $prop['email_template'] ),
99
- 'to' => array(
100
- array(
101
- 'name' => sprintf(
102
- '%1$s %2$s',
103
- $attributes['FIRSTNAME'],
104
- $attributes['LASTNAME']
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
  ),
106
- 'email' => $attributes['EMAIL'],
107
  ),
108
- ),
109
- 'params' => (object) $attributes,
110
- 'tags' => array( 'Contact Form 7' ),
111
- ) );
 
 
112
  }
113
 
114
 
80
  return;
81
  }
82
 
83
+ $contact_params = apply_filters(
84
+ 'wpcf7_sendinblue_contact_parameters',
85
+ array(
86
+ 'email' => $attributes['EMAIL'],
87
+ 'attributes' => (object) $attributes,
88
+ 'listIds' => (array) $prop['contact_lists'],
89
+ 'updateEnabled' => false,
90
+ )
91
+ );
92
+
93
+ $contact_id = $service->create_contact( $contact_params );
94
 
95
  if ( ! $contact_id ) {
96
  return;
100
  return;
101
  }
102
 
103
+ $first_name = isset( $attributes['FIRSTNAME'] )
104
+ ? trim( $attributes['FIRSTNAME'] )
105
+ : '';
106
+
107
+ $last_name = isset( $attributes['LASTNAME'] )
108
+ ? trim( $attributes['LASTNAME'] )
109
+ : '';
110
+
111
+ if ( $first_name or $last_name ) {
112
+ $email_to_name = sprintf(
113
+ /* translators: 1: first name, 2: last name */
114
+ _x( '%1$s %2$s', 'personal name', 'contact-form-7' ),
115
+ $first_name,
116
+ $last_name
117
+ );
118
+ } else {
119
+ $email_to_name = '';
120
+ }
121
+
122
+ $email_params = apply_filters(
123
+ 'wpcf7_sendinblue_email_parameters',
124
+ array(
125
+ 'templateId' => absint( $prop['email_template'] ),
126
+ 'to' => array(
127
+ array(
128
+ 'name' => $email_to_name,
129
+ 'email' => $attributes['EMAIL'],
130
  ),
 
131
  ),
132
+ 'params' => (object) $attributes,
133
+ 'tags' => array( 'Contact Form 7' ),
134
+ )
135
+ );
136
+
137
+ $service->send_email( $email_params );
138
  }
139
 
140
 
modules/stripe/api.php ADDED
@@ -0,0 +1,154 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class for the Stripe API.
5
+ *
6
+ * @link https://stripe.com/docs/api
7
+ */
8
+ class WPCF7_Stripe_API {
9
+
10
+ const api_version = '2020-08-27';
11
+ const partner_id = 'pp_partner_HHbvqLh1AaO7Am';
12
+ const app_name = 'WordPress Contact Form 7';
13
+ const app_url = 'https://contactform7.com/stripe-integration/';
14
+
15
+ private $secret;
16
+
17
+
18
+ /**
19
+ * Constructor.
20
+ *
21
+ * @param string $secret Secret key.
22
+ */
23
+ public function __construct( $secret ) {
24
+ $this->secret = $secret;
25
+ }
26
+
27
+
28
+ /**
29
+ * Sends a debug information for a remote request to the PHP error log.
30
+ *
31
+ * @param string $url URL to retrieve.
32
+ * @param array $request Request arguments.
33
+ * @param array|WP_Error $response The response or WP_Error on failure.
34
+ */
35
+ private function log( $url, $request, $response ) {
36
+ wpcf7_log_remote_request( $url, $request, $response );
37
+ }
38
+
39
+
40
+ /**
41
+ * Returns default set of HTTP request headers used for Stripe API.
42
+ *
43
+ * @link https://stripe.com/docs/building-plugins#setappinfo
44
+ *
45
+ * @return array An associative array of headers.
46
+ */
47
+ private function default_headers() {
48
+ $app_info = array(
49
+ 'name' => self::app_name,
50
+ 'partner_id' => self::partner_id,
51
+ 'url' => self::app_url,
52
+ 'version' => WPCF7_VERSION,
53
+ );
54
+
55
+ $ua = array(
56
+ 'lang' => 'php',
57
+ 'lang_version' => PHP_VERSION,
58
+ 'application' => $app_info,
59
+ );
60
+
61
+ $headers = array(
62
+ 'Authorization' => sprintf( 'Bearer %s', $this->secret ),
63
+ 'Stripe-Version' => self::api_version,
64
+ 'X-Stripe-Client-User-Agent' => json_encode( $ua ),
65
+ 'User-Agent' => sprintf(
66
+ '%1$s/%2$s (%3$s)',
67
+ self::app_name,
68
+ WPCF7_VERSION,
69
+ self::app_url
70
+ ),
71
+ );
72
+
73
+ return $headers;
74
+ }
75
+
76
+
77
+ /**
78
+ * Creates a Payment Intent.
79
+ *
80
+ * @link https://stripe.com/docs/api/payment_intents/create
81
+ *
82
+ * @param string|array $args Optional. Arguments to control behavior.
83
+ * @return array|bool An associative array if 200 OK, false otherwise.
84
+ */
85
+ public function create_payment_intent( $args = '' ) {
86
+ $args = wp_parse_args( $args, array(
87
+ 'amount' => 0,
88
+ 'currency' => '',
89
+ 'receipt_email' => '',
90
+ ) );
91
+
92
+ if ( ! is_email( $args['receipt_email'] ) ) {
93
+ unset( $args['receipt_email'] );
94
+ }
95
+
96
+ $endpoint = 'https://api.stripe.com/v1/payment_intents';
97
+
98
+ $request = array(
99
+ 'headers' => $this->default_headers(),
100
+ 'body' => $args,
101
+ );
102
+
103
+ $response = wp_remote_post( esc_url_raw( $endpoint ), $request );
104
+
105
+ if ( 200 != wp_remote_retrieve_response_code( $response ) ) {
106
+ if ( WP_DEBUG ) {
107
+ $this->log( $endpoint, $request, $response );
108
+ }
109
+
110
+ return false;
111
+ }
112
+
113
+ $response_body = wp_remote_retrieve_body( $response );
114
+ $response_body = json_decode( $response_body, true );
115
+
116
+ return $response_body;
117
+ }
118
+
119
+
120
+ /**
121
+ * Retrieve a Payment Intent.
122
+ *
123
+ * @link https://stripe.com/docs/api/payment_intents/retrieve
124
+ *
125
+ * @param string $id Payment Intent identifier.
126
+ * @return array|bool An associative array if 200 OK, false otherwise.
127
+ */
128
+ public function retrieve_payment_intent( $id ) {
129
+ $endpoint = sprintf(
130
+ 'https://api.stripe.com/v1/payment_intents/%s',
131
+ urlencode( $id )
132
+ );
133
+
134
+ $request = array(
135
+ 'headers' => $this->default_headers(),
136
+ );
137
+
138
+ $response = wp_remote_get( esc_url_raw( $endpoint ), $request );
139
+
140
+ if ( 200 != wp_remote_retrieve_response_code( $response ) ) {
141
+ if ( WP_DEBUG ) {
142
+ $this->log( $endpoint, $request, $response );
143
+ }
144
+
145
+ return false;
146
+ }
147
+
148
+ $response_body = wp_remote_retrieve_body( $response );
149
+ $response_body = json_decode( $response_body, true );
150
+
151
+ return $response_body;
152
+ }
153
+
154
+ }
modules/stripe/index.js ADDED
@@ -0,0 +1 @@
 
1
+ document.addEventListener("DOMContentLoaded",(e=>{const t=()=>{const e=document.querySelectorAll("form.wpcf7-form .wpcf7-stripe");for(let t=0;t<e.length;t++){let r=e[t];r.querySelector("button").disabled=!0;let i=document.createElement("span");i.setAttribute("class","wpcf7-not-valid-tip"),i.insertAdjacentText("beforeend","This form includes a payment widget that requires a modern browser to work."),r.appendChild(i)}};if(void 0===window.wpcf7_stripe)return console.error("window.wpcf7_stripe is not defined."),void t();if("function"!=typeof window.Stripe)return console.error("window.Stripe is not defined."),void t();if("function"!=typeof wpcf7.submit)return console.error("wpcf7.submit is not defined."),void t();const r=Stripe(wpcf7_stripe.publishable_key),i=r.elements();document.addEventListener("wpcf7submit",(e=>{const t=e.detail.unitTag,s=`${t}-ve-stripe-card-element`,n=document.querySelector(`#${t} form`),o=n.closest(".wpcf7").querySelector(".screen-reader-response"),d=n.querySelector(".wpcf7-stripe .wpcf7-form-control-wrap"),c=n.querySelector(".wpcf7-stripe button.first"),a=n.querySelector(".wpcf7-stripe button.second"),l=n.querySelector('[name="_wpcf7_stripe_payment_intent"]');if(!l)return;l.setAttribute("value","");const u=e=>{const t=o.querySelector("ul"),r=t.querySelector(`li#${s}`);r&&r.remove();const i=document.createElement("li");i.setAttribute("id",s),i.insertAdjacentText("beforeend",e.message),t.appendChild(i)},p=e=>{const t=d.querySelector(".wpcf7-form-control");t.classList.add("wpcf7-not-valid"),t.setAttribute("aria-describedby",s);const r=document.createElement("span");r.setAttribute("class","wpcf7-not-valid-tip"),r.setAttribute("aria-hidden","true"),r.insertAdjacentText("beforeend",e.message),d.appendChild(r),d.querySelectorAll("[aria-invalid]").forEach((e=>{e.setAttribute("aria-invalid","true")})),t.closest(".use-floating-validation-tip")&&(t.addEventListener("focus",(e=>{r.setAttribute("style","display: none")})),r.addEventListener("mouseover",(e=>{r.setAttribute("style","display: none")})))},f=()=>{o.querySelectorAll(`ul li#${s}`).forEach((e=>{e.remove()})),d.querySelectorAll(".wpcf7-not-valid-tip").forEach((e=>{e.remove()})),d.querySelectorAll("[aria-invalid]").forEach((e=>{e.setAttribute("aria-invalid","false")})),d.querySelectorAll(".wpcf7-form-control").forEach((e=>{e.removeAttribute("aria-describedby"),e.classList.remove("wpcf7-not-valid")}))};if("payment_required"===e.detail.status){const s=e.detail.apiResponse.stripe.payment_intent;s.id&&l.setAttribute("value",s.id);const o=i.getElement("card")||i.create("card");o.mount(`#${t} .wpcf7-stripe .card-element`),o.clear(),d.classList.remove("hidden"),c.classList.add("hidden"),a.classList.remove("hidden"),a.disabled=!0,o.addEventListener("change",(e=>{if(f(),e.error){const t={message:e.error.message};u(t),p(t),a.disabled=!0}else a.disabled=!1})),a.addEventListener("click",(e=>{f(),a.disabled=!0,n.classList.add("submitting"),wpcf7.blocked||r.confirmCardPayment(s.client_secret,{payment_method:{card:o}}).then((e=>{if(e.error){e.error.decline_code&&["fraudulent","lost_card","merchant_blacklist","pickup_card","restricted_card","security_violation","service_not_allowed","stolen_card","transaction_not_allowed"].includes(e.error.decline_code)&&(wpcf7.blocked=!0),n.classList.remove("submitting");const t={message:e.error.message};u(t),p(t)}else"succeeded"===e.paymentIntent.status&&wpcf7.submit(n)}))}))}else d.classList.add("hidden"),c.classList.remove("hidden"),a.classList.add("hidden"),["mail_sent","mail_failed"].includes(e.detail.status)&&(c.disabled=!0)}))}));
modules/stripe/service.php ADDED
@@ -0,0 +1,255 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! class_exists( 'WPCF7_Service' ) ) {
4
+ return;
5
+ }
6
+
7
+ class WPCF7_Stripe extends WPCF7_Service {
8
+
9
+ private static $instance;
10
+ private $api_keys;
11
+
12
+
13
+ public static function get_instance() {
14
+ if ( empty( self::$instance ) ) {
15
+ self::$instance = new self;
16
+ }
17
+
18
+ return self::$instance;
19
+ }
20
+
21
+
22
+ private function __construct() {
23
+ $option = WPCF7::get_option( 'stripe' );
24
+
25
+ if ( isset( $option['api_keys']['publishable'] )
26
+ and isset( $option['api_keys']['secret'] ) ) {
27
+ $this->api_keys = array(
28
+ 'publishable' => $option['api_keys']['publishable'],
29
+ 'secret' => $option['api_keys']['secret'],
30
+ );
31
+ }
32
+ }
33
+
34
+
35
+ public function get_title() {
36
+ return __( 'Stripe', 'contact-form-7' );
37
+ }
38
+
39
+
40
+ public function is_active() {
41
+ return (bool) $this->get_api_keys();
42
+ }
43
+
44
+
45
+ public function api() {
46
+ if ( $this->is_active() ) {
47
+ $api = new WPCF7_Stripe_API( $this->api_keys['secret'] );
48
+ return $api;
49
+ }
50
+ }
51
+
52
+
53
+ public function get_api_keys() {
54
+ return $this->api_keys;
55
+ }
56
+
57
+
58
+ public function get_categories() {
59
+ return array( 'payments' );
60
+ }
61
+
62
+
63
+ public function icon() {
64
+ }
65
+
66
+
67
+ public function link() {
68
+ echo wpcf7_link(
69
+ 'https://stripe.com/',
70
+ 'stripe.com'
71
+ );
72
+ }
73
+
74
+
75
+ protected function menu_page_url( $args = '' ) {
76
+ $args = wp_parse_args( $args, array() );
77
+
78
+ $url = menu_page_url( 'wpcf7-integration', false );
79
+ $url = add_query_arg( array( 'service' => 'stripe' ), $url );
80
+
81
+ if ( ! empty( $args ) ) {
82
+ $url = add_query_arg( $args, $url );
83
+ }
84
+
85
+ return $url;
86
+ }
87
+
88
+
89
+ protected function save_data() {
90
+ WPCF7::update_option( 'stripe', array(
91
+ 'api_keys' => $this->api_keys,
92
+ ) );
93
+ }
94
+
95
+
96
+ protected function reset_data() {
97
+ $this->api_keys = null;
98
+ $this->save_data();
99
+ }
100
+
101
+
102
+ public function load( $action = '' ) {
103
+ if ( 'setup' == $action and 'POST' == $_SERVER['REQUEST_METHOD'] ) {
104
+ check_admin_referer( 'wpcf7-stripe-setup' );
105
+
106
+ if ( ! empty( $_POST['reset'] ) ) {
107
+ $this->reset_data();
108
+ $redirect_to = $this->menu_page_url( 'action=setup' );
109
+ } else {
110
+ $publishable = isset( $_POST['publishable'] ) ?
111
+ trim( $_POST['publishable'] ) : '';
112
+ $secret = isset( $_POST['secret'] ) ? trim( $_POST['secret'] ) : '';
113
+
114
+ if ( $publishable and $secret ) {
115
+ $this->api_keys = array(
116
+ 'publishable' => $publishable,
117
+ 'secret' => $secret,
118
+ );
119
+ $this->save_data();
120
+
121
+ $redirect_to = $this->menu_page_url( array(
122
+ 'message' => 'success',
123
+ ) );
124
+ } else {
125
+ $redirect_to = $this->menu_page_url( array(
126
+ 'action' => 'setup',
127
+ 'message' => 'invalid',
128
+ ) );
129
+ }
130
+ }
131
+
132
+ wp_safe_redirect( $redirect_to );
133
+ exit();
134
+ }
135
+ }
136
+
137
+
138
+ public function admin_notice( $message = '' ) {
139
+ if ( 'invalid' == $message ) {
140
+ echo sprintf(
141
+ '<div class="notice notice-error"><p><strong>%1$s</strong>: %2$s</p></div>',
142
+ esc_html( __( "Error", 'contact-form-7' ) ),
143
+ esc_html( __( "Invalid key values.", 'contact-form-7' ) )
144
+ );
145
+ }
146
+
147
+ if ( 'success' == $message ) {
148
+ echo sprintf(
149
+ '<div class="notice notice-success"><p>%s</p></div>',
150
+ esc_html( __( 'Settings saved.', 'contact-form-7' ) )
151
+ );
152
+ }
153
+ }
154
+
155
+
156
+ public function display( $action = '' ) {
157
+ // https://stripe.com/docs/partners/support#intro
158
+ echo '<p>' . sprintf(
159
+ esc_html( __( 'Stripe is a simple and powerful way to accept payments online. Stripe has no setup fees, no monthly fees, and no hidden costs. Millions of businesses rely on Stripe’s software tools to accept payments securely and expand globally. For details, see %s.', 'contact-form-7' ) ),
160
+ wpcf7_link(
161
+ __( 'https://contactform7.com/stripe-integration/', 'contact-form-7' ),
162
+ __( 'Stripe integration', 'contact-form-7' )
163
+ )
164
+ ) . '</p>';
165
+
166
+ if ( $this->is_active() ) {
167
+ echo sprintf(
168
+ '<p class="dashicons-before dashicons-yes">%s</p>',
169
+ esc_html( __( "Stripe is active on this site.", 'contact-form-7' ) )
170
+ );
171
+ }
172
+
173
+ if ( 'setup' == $action ) {
174
+ $this->display_setup();
175
+ } elseif ( is_ssl() or WP_DEBUG ) {
176
+ echo sprintf(
177
+ '<p><a href="%1$s" class="button">%2$s</a></p>',
178
+ esc_url( $this->menu_page_url( 'action=setup' ) ),
179
+ esc_html( __( 'Setup Integration', 'contact-form-7' ) )
180
+ );
181
+ } else {
182
+ echo sprintf(
183
+ '<p class="dashicons-before dashicons-warning">%s</p>',
184
+ esc_html( __( "Stripe is not available on this site. It requires an HTTPS-enabled site.", 'contact-form-7' ) )
185
+ );
186
+ }
187
+ }
188
+
189
+
190
+ private function display_setup() {
191
+ $api_keys = $this->get_api_keys();
192
+
193
+ if ( $api_keys ) {
194
+ $publishable = $api_keys['publishable'];
195
+ $secret = $api_keys['secret'];
196
+ } else {
197
+ $publishable = '';
198
+ $secret = '';
199
+ }
200
+
201
+ ?>
202
+ <form method="post" action="<?php echo esc_url( $this->menu_page_url( 'action=setup' ) ); ?>">
203
+ <?php wp_nonce_field( 'wpcf7-stripe-setup' ); ?>
204
+ <table class="form-table">
205
+ <tbody>
206
+ <tr>
207
+ <th scope="row"><label for="publishable"><?php echo esc_html( __( 'Publishable Key', 'contact-form-7' ) ); ?></label></th>
208
+ <td><?php
209
+ if ( $this->is_active() ) {
210
+ echo esc_html( $publishable );
211
+ echo sprintf(
212
+ '<input type="hidden" value="%s" id="publishable" name="publishable" />',
213
+ esc_attr( $publishable )
214
+ );
215
+ } else {
216
+ echo sprintf(
217
+ '<input type="text" aria-required="true" value="%s" id="publishable" name="publishable" class="regular-text code" />',
218
+ esc_attr( $publishable )
219
+ );
220
+ }
221
+ ?></td>
222
+ </tr>
223
+ <tr>
224
+ <th scope="row"><label for="secret"><?php echo esc_html( __( 'Secret Key', 'contact-form-7' ) ); ?></label></th>
225
+ <td><?php
226
+ if ( $this->is_active() ) {
227
+ echo esc_html( wpcf7_mask_password( $secret ) );
228
+ echo sprintf(
229
+ '<input type="hidden" value="%s" id="secret" name="secret" />',
230
+ esc_attr( $secret )
231
+ );
232
+ } else {
233
+ echo sprintf(
234
+ '<input type="text" aria-required="true" value="%s" id="secret" name="secret" class="regular-text code" />',
235
+ esc_attr( $secret )
236
+ );
237
+ }
238
+ ?></td>
239
+ </tr>
240
+ </tbody>
241
+ </table>
242
+ <?php
243
+ if ( $this->is_active() ) {
244
+ submit_button(
245
+ _x( 'Remove Keys', 'API keys', 'contact-form-7' ),
246
+ 'small', 'reset'
247
+ );
248
+ } else {
249
+ submit_button( __( 'Save Changes', 'contact-form-7' ) );
250
+ }
251
+ ?>
252
+ </form>
253
+ <?php
254
+ }
255
+ }
modules/stripe/stripe.php ADDED
@@ -0,0 +1,338 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ include_once path_join( WPCF7_PLUGIN_MODULES_DIR, 'stripe/service.php' );
4
+ include_once path_join( WPCF7_PLUGIN_MODULES_DIR, 'stripe/api.php' );
5
+
6
+
7
+ add_action(
8
+ 'wpcf7_init',
9
+ 'wpcf7_stripe_register_service',
10
+ 10, 0
11
+ );
12
+
13
+ /**
14
+ * Registers the Stripe service.
15
+ */
16
+ function wpcf7_stripe_register_service() {
17
+ $integration = WPCF7_Integration::get_instance();
18
+
19
+ $integration->add_category( 'payments',
20
+ __( 'Payments', 'contact-form-7' )
21
+ );
22
+
23
+ $integration->add_service( 'stripe',
24
+ WPCF7_Stripe::get_instance()
25
+ );
26
+ }
27
+
28
+
29
+ add_action(
30
+ 'wpcf7_enqueue_scripts',
31
+ 'wpcf7_stripe_enqueue_scripts',
32
+ 10, 0
33
+ );
34
+
35
+ /**
36
+ * Enqueues scripts and styles for the Stripe module.
37
+ */
38
+ function wpcf7_stripe_enqueue_scripts() {
39
+ $service = WPCF7_Stripe::get_instance();
40
+
41
+ if ( ! $service->is_active() ) {
42
+ return;
43
+ }
44
+
45
+ wp_enqueue_style( 'wpcf7-stripe',
46
+ wpcf7_plugin_url( 'modules/stripe/style.css' ),
47
+ array(), WPCF7_VERSION, 'all'
48
+ );
49
+
50
+ wp_enqueue_script( 'stripe',
51
+ 'https://js.stripe.com/v3/',
52
+ array(), null
53
+ );
54
+
55
+ $assets = array();
56
+
57
+ $asset_file = wpcf7_plugin_path( 'modules/stripe/index.asset.php' );
58
+
59
+ if ( file_exists( $asset_file ) ) {
60
+ $assets = include( $asset_file );
61
+ }
62
+
63
+ $assets = wp_parse_args( $assets, array(
64
+ 'src' => wpcf7_plugin_url( 'modules/stripe/index.js' ),
65
+ 'dependencies' => array(
66
+ 'wp-polyfill',
67
+ ),
68
+ 'version' => WPCF7_VERSION,
69
+ ) );
70
+
71
+ wp_enqueue_script(
72
+ 'wpcf7-stripe',
73
+ $assets['src'],
74
+ array_merge( array(
75
+ 'contact-form-7',
76
+ 'stripe',
77
+ ), $assets['dependencies'] ),
78
+ $assets['version'],
79
+ true
80
+ );
81
+
82
+ $api_keys = $service->get_api_keys();
83
+
84
+ if ( $api_keys['publishable'] ) {
85
+ wp_localize_script( 'wpcf7-stripe', 'wpcf7_stripe', array(
86
+ 'publishable_key' => $api_keys['publishable'],
87
+ ) );
88
+ }
89
+ }
90
+
91
+
92
+ add_filter(
93
+ 'wpcf7_skip_spam_check',
94
+ 'wpcf7_stripe_skip_spam_check',
95
+ 10, 2
96
+ );
97
+
98
+ /**
99
+ * Skips the spam check if it is not necessary.
100
+ *
101
+ * @return bool True if the spam check is not necessary.
102
+ */
103
+ function wpcf7_stripe_skip_spam_check( $skip_spam_check, $submission ) {
104
+ $service = WPCF7_Stripe::get_instance();
105
+
106
+ if ( ! $service->is_active() ) {
107
+ return $skip_spam_check;
108
+ }
109
+
110
+ if ( ! empty( $_POST['_wpcf7_stripe_payment_intent'] ) ) {
111
+ $pi_id = trim( $_POST['_wpcf7_stripe_payment_intent'] );
112
+ $payment_intent = $service->api()->retrieve_payment_intent( $pi_id );
113
+
114
+ if ( isset( $payment_intent['status'] )
115
+ and ( 'succeeded' === $payment_intent['status'] ) ) {
116
+ $submission->payment_intent = $pi_id;
117
+ }
118
+ }
119
+
120
+ if ( ! empty( $submission->payment_intent )
121
+ and $submission->verify_posted_data_hash() ) {
122
+ $skip_spam_check = true;
123
+ }
124
+
125
+ return $skip_spam_check;
126
+ }
127
+
128
+
129
+ add_action(
130
+ 'wpcf7_before_send_mail',
131
+ 'wpcf7_stripe_before_send_mail',
132
+ 10, 3
133
+ );
134
+
135
+ /**
136
+ * Creates Stripe's Payment Intent.
137
+ */
138
+ function wpcf7_stripe_before_send_mail( $contact_form, &$abort, $submission ) {
139
+ $service = WPCF7_Stripe::get_instance();
140
+
141
+ if ( ! $service->is_active() ) {
142
+ return;
143
+ }
144
+
145
+ $tags = $contact_form->scan_form_tags( array( 'type' => 'stripe' ) );
146
+
147
+ if ( ! $tags ) {
148
+ return;
149
+ }
150
+
151
+ if ( ! empty( $submission->payment_intent ) ) {
152
+ return;
153
+ }
154
+
155
+ $tag = $tags[0];
156
+ $amount = $tag->get_option( 'amount', 'int', true );
157
+ $currency = $tag->get_option( 'currency', '[a-zA-Z]{3}', true );
158
+
159
+ $payment_intent_params = apply_filters(
160
+ 'wpcf7_stripe_payment_intent_parameters',
161
+ array(
162
+ 'amount' => $amount ? absint( $amount ) : null,
163
+ 'currency' => $currency ? strtolower( $currency ) : null,
164
+ 'receipt_email' => $submission->get_posted_data( 'your-email' ),
165
+ )
166
+ );
167
+
168
+ $payment_intent = $service->api()->create_payment_intent(
169
+ $payment_intent_params
170
+ );
171
+
172
+ if ( $payment_intent ) {
173
+ $submission->add_result_props( array(
174
+ 'stripe' => array(
175
+ 'payment_intent' => array(
176
+ 'id' => $payment_intent['id'],
177
+ 'client_secret' => $payment_intent['client_secret'],
178
+ ),
179
+ ),
180
+ ) );
181
+
182
+ $submission->set_status( 'payment_required' );
183
+
184
+ $submission->set_response(
185
+ __( "Payment is required. Please pay by credit card.", 'contact-form-7' )
186
+ );
187
+ }
188
+
189
+ $abort = true;
190
+ }
191
+
192
+
193
+ /**
194
+ * Returns payment link URL.
195
+ *
196
+ * @param string $pi_id Payment Intent ID.
197
+ * @return string The URL.
198
+ */
199
+ function wpcf7_stripe_get_payment_link( $pi_id ) {
200
+ return sprintf(
201
+ 'https://dashboard.stripe.com/payments/%s',
202
+ urlencode( $pi_id )
203
+ );
204
+ }
205
+
206
+
207
+ add_filter(
208
+ 'wpcf7_special_mail_tags',
209
+ 'wpcf7_stripe_smt',
210
+ 10, 4
211
+ );
212
+
213
+ /**
214
+ * Registers the [_stripe_payment_link] special mail-tag.
215
+ */
216
+ function wpcf7_stripe_smt( $output, $tag_name, $html, $mail_tag ) {
217
+ if ( '_stripe_payment_link' === $tag_name ) {
218
+ $submission = WPCF7_Submission::get_instance();
219
+
220
+ if ( ! empty( $submission->payment_intent ) ) {
221
+ $output = wpcf7_stripe_get_payment_link( $submission->payment_intent );
222
+ }
223
+ }
224
+
225
+ return $output;
226
+ }
227
+
228
+
229
+ add_filter(
230
+ 'wpcf7_flamingo_inbound_message_parameters',
231
+ 'wpcf7_stripe_add_flamingo_inbound_message_params',
232
+ 10, 1
233
+ );
234
+
235
+ /**
236
+ * Adds Stripe-related meta data to Flamingo Inbound Message parameters.
237
+ */
238
+ function wpcf7_stripe_add_flamingo_inbound_message_params( $args ) {
239
+ $submission = WPCF7_Submission::get_instance();
240
+
241
+ if ( empty( $submission->payment_intent ) ) {
242
+ return $args;
243
+ }
244
+
245
+ $pi_link = wpcf7_stripe_get_payment_link( $submission->payment_intent );
246
+
247
+ $meta = (array) $args['meta'];
248
+
249
+ $meta['stripe_payment_link'] = $pi_link;
250
+
251
+ $args['meta'] = $meta;
252
+
253
+ return $args;
254
+ }
255
+
256
+
257
+ add_action(
258
+ 'wpcf7_init',
259
+ 'wpcf7_add_form_tag_stripe',
260
+ 10, 0
261
+ );
262
+
263
+ /**
264
+ * Registers the stripe form-tag handler.
265
+ */
266
+ function wpcf7_add_form_tag_stripe() {
267
+ wpcf7_add_form_tag(
268
+ 'stripe',
269
+ 'wpcf7_stripe_form_tag_handler',
270
+ array(
271
+ 'display-block' => true,
272
+ 'singular' => true,
273
+ )
274
+ );
275
+ }
276
+
277
+
278
+ /**
279
+ * Defines the stripe form-tag handler.
280
+ *
281
+ * @return string HTML content that replaces a stripe form-tag.
282
+ */
283
+ function wpcf7_stripe_form_tag_handler( $tag ) {
284
+ $card_element = sprintf(
285
+ '<div %s></div>',
286
+ wpcf7_format_atts( array(
287
+ 'class' => 'card-element wpcf7-form-control',
288
+ 'aria-invalid' => 'false',
289
+ ) )
290
+ );
291
+
292
+ $card_element = sprintf(
293
+ '<div class="wpcf7-form-control-wrap hidden">%s</div>',
294
+ $card_element
295
+ );
296
+
297
+ $button_1_label = __( 'Proceed to checkout', 'contact-form-7' );
298
+
299
+ if ( isset( $tag->values[0] ) ) {
300
+ $button_1_label = trim( $tag->values[0] );
301
+ }
302
+
303
+ $button_1 = sprintf(
304
+ '<button %1$s>%2$s</button>',
305
+ wpcf7_format_atts( array(
306
+ 'type' => 'submit',
307
+ 'class' => 'first',
308
+ ) ),
309
+ esc_html( $button_1_label )
310
+ );
311
+
312
+ $button_2_label = __( 'Complete payment', 'contact-form-7' );
313
+
314
+ if ( isset( $tag->values[1] ) ) {
315
+ $button_2_label = trim( $tag->values[1] );
316
+ }
317
+
318
+ $button_2 = sprintf(
319
+ '<button %1$s>%2$s</button>',
320
+ wpcf7_format_atts( array(
321
+ 'type' => 'button',
322
+ 'class' => 'second hidden',
323
+ ) ),
324
+ esc_html( $button_2_label )
325
+ );
326
+
327
+ $buttons = sprintf(
328
+ '<span class="buttons has-spinner">%1$s %2$s</span>',
329
+ $button_1, $button_2
330
+ );
331
+
332
+ return sprintf(
333
+ '<div class="wpcf7-stripe">%1$s %2$s %3$s</div>',
334
+ $card_element,
335
+ $buttons,
336
+ '<input type="hidden" name="_wpcf7_stripe_payment_intent" value="" />'
337
+ );
338
+ }
modules/stripe/style.css ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .wpcf7 .wpcf7-stripe .wpcf7-form-control-wrap {
2
+ margin: .6em 0;
3
+ }
4
+
5
+ .wpcf7 .wpcf7-stripe .wpcf7-form-control {
6
+ display: block;
7
+ background: #f6f7f7;
8
+ padding: 12px 12px;
9
+ border: 1px solid #787c82;
10
+ }
11
+
12
+ .wpcf7 .wpcf7-stripe button:disabled {
13
+ cursor: not-allowed;
14
+ }
15
+
16
+ .wpcf7 .wpcf7-stripe .hidden {
17
+ display: none;
18
+ }
modules/submit.php CHANGED
@@ -12,7 +12,7 @@ function wpcf7_add_form_tag_submit() {
12
  }
13
 
14
  function wpcf7_submit_form_tag_handler( $tag ) {
15
- $class = wpcf7_form_controls_class( $tag->type );
16
 
17
  $atts = array();
18
 
12
  }
13
 
14
  function wpcf7_submit_form_tag_handler( $tag ) {
15
+ $class = wpcf7_form_controls_class( $tag->type, 'has-spinner' );
16
 
17
  $atts = array();
18
 
modules/text.php CHANGED
@@ -162,7 +162,7 @@ function wpcf7_text_validation_filter( $result, $tag ) {
162
  $maxlength = $minlength = null;
163
  }
164
 
165
- $code_units = wpcf7_count_code_units( stripslashes( $value ) );
166
 
167
  if ( false !== $code_units ) {
168
  if ( $maxlength and $maxlength < $code_units ) {
162
  $maxlength = $minlength = null;
163
  }
164
 
165
+ $code_units = wpcf7_count_code_units( $value );
166
 
167
  if ( false !== $code_units ) {
168
  if ( $maxlength and $maxlength < $code_units ) {
modules/textarea.php CHANGED
@@ -101,7 +101,9 @@ function wpcf7_textarea_validation_filter( $result, $tag ) {
101
  $type = $tag->type;
102
  $name = $tag->name;
103
 
104
- $value = isset( $_POST[$name] ) ? (string) $_POST[$name] : '';
 
 
105
 
106
  if ( $tag->is_required() and '' === $value ) {
107
  $result->invalidate( $tag, wpcf7_get_message( 'invalid_required' ) );
@@ -116,7 +118,7 @@ function wpcf7_textarea_validation_filter( $result, $tag ) {
116
  $maxlength = $minlength = null;
117
  }
118
 
119
- $code_units = wpcf7_count_code_units( stripslashes( $value ) );
120
 
121
  if ( false !== $code_units ) {
122
  if ( $maxlength and $maxlength < $code_units ) {
101
  $type = $tag->type;
102
  $name = $tag->name;
103
 
104
+ $value = isset( $_POST[$name] )
105
+ ? wp_unslash( (string) $_POST[$name] )
106
+ : '';
107
 
108
  if ( $tag->is_required() and '' === $value ) {
109
  $result->invalidate( $tag, wpcf7_get_message( 'invalid_required' ) );
118
  $maxlength = $minlength = null;
119
  }
120
 
121
+ $code_units = wpcf7_count_code_units( $value );
122
 
123
  if ( false !== $code_units ) {
124
  if ( $maxlength and $maxlength < $code_units ) {
readme.txt CHANGED
@@ -2,9 +2,9 @@
2
  Contributors: takayukister
3
  Donate link: https://contactform7.com/donate/
4
  Tags: contact, form, contact form, feedback, email, ajax, captcha, akismet, multilingual
5
- Requires at least: 5.5
6
  Tested up to: 5.8
7
- Stable tag: 5.4.2
8
  License: GPLv2 or later
9
  License URI: https://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -37,6 +37,7 @@ If you activate certain features in this plugin, the contact form submitter's pe
37
  * Akismet ([Automattic](https://automattic.com/privacy/))
38
  * Constant Contact ([Endurance International Group](https://www.endurance.com/privacy))
39
  * [Sendinblue](https://www.sendinblue.com/legal/privacypolicy/)
 
40
 
41
  = Recommended plugins =
42
 
@@ -76,6 +77,10 @@ Do you have questions or issues with Contact Form 7? Use these support channels
76
 
77
  For more information, see [Releases](https://contactform7.com/category/releases/).
78
 
 
 
 
 
79
  = 5.4.2 =
80
 
81
  [https://contactform7.com/contact-form-7-542/](https://contactform7.com/contact-form-7-542/)
2
  Contributors: takayukister
3
  Donate link: https://contactform7.com/donate/
4
  Tags: contact, form, contact form, feedback, email, ajax, captcha, akismet, multilingual
5
+ Requires at least: 5.7
6
  Tested up to: 5.8
7
+ Stable tag: 5.5
8
  License: GPLv2 or later
9
  License URI: https://www.gnu.org/licenses/gpl-2.0.html
10
 
37
  * Akismet ([Automattic](https://automattic.com/privacy/))
38
  * Constant Contact ([Endurance International Group](https://www.endurance.com/privacy))
39
  * [Sendinblue](https://www.sendinblue.com/legal/privacypolicy/)
40
+ * [Stripe](https://stripe.com/privacy)
41
 
42
  = Recommended plugins =
43
 
77
 
78
  For more information, see [Releases](https://contactform7.com/category/releases/).
79
 
80
+ = 5.5 =
81
+
82
+ [https://contactform7.com/contact-form-7-55/](https://contactform7.com/contact-form-7-55/)
83
+
84
  = 5.4.2 =
85
 
86
  [https://contactform7.com/contact-form-7-542/](https://contactform7.com/contact-form-7-542/)
uninstall.php CHANGED
@@ -21,8 +21,12 @@ function wpcf7_delete_plugin() {
21
  wp_delete_post( $post->ID, true );
22
  }
23
 
24
- $wpdb->query( sprintf( "DROP TABLE IF EXISTS %s",
25
- $wpdb->prefix . 'contact_form_7' ) );
 
 
26
  }
27
 
28
- wpcf7_delete_plugin();
 
 
21
  wp_delete_post( $post->ID, true );
22
  }
23
 
24
+ $wpdb->query( sprintf(
25
+ "DROP TABLE IF EXISTS %s",
26
+ $wpdb->prefix . 'contact_form_7'
27
+ ) );
28
  }
29
 
30
+ if ( ! defined( 'WPCF7_VERSION' ) ) {
31
+ wpcf7_delete_plugin();
32
+ }
wp-contact-form-7.php CHANGED
@@ -7,12 +7,12 @@ Author: Takayuki Miyoshi
7
  Author URI: https://ideasilo.wordpress.com/
8
  Text Domain: contact-form-7
9
  Domain Path: /languages/
10
- Version: 5.4.2
11
  */
12
 
13
- define( 'WPCF7_VERSION', '5.4.2' );
14
 
15
- define( 'WPCF7_REQUIRED_WP_VERSION', '5.5' );
16
 
17
  define( 'WPCF7_TEXT_DOMAIN', 'contact-form-7' );
18
 
7
  Author URI: https://ideasilo.wordpress.com/
8
  Text Domain: contact-form-7
9
  Domain Path: /languages/
10
+ Version: 5.5
11
  */
12
 
13
+ define( 'WPCF7_VERSION', '5.5' );
14
 
15
+ define( 'WPCF7_REQUIRED_WP_VERSION', '5.7' );
16
 
17
  define( 'WPCF7_TEXT_DOMAIN', 'contact-form-7' );
18