PluginProbe ʕ •ᴥ•ʔ
Contact Form 7 / 5.5.5
Contact Form 7 v5.5.5
6.1.6 5.0.2 5.0.3 5.0.4 5.0.5 5.1 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.1.8 5.1.9 5.2 5.2.1 5.2.2 5.3 5.3.1 5.3.2 5.4 5.4.1 5.4.2 5.5 5.5.1 5.5.2 5.5.3 5.5.4 5.5.5 5.5.6 5.5.6.1 5.6 5.6.1 5.6.2 5.6.3 5.6.4 5.7 5.7.1 5.7.2 5.7.3 5.7.4 5.7.5 5.7.5.1 5.7.6 5.7.7 5.8 5.8.1 5.8.2 5.8.3 5.8.4 5.8.5 5.8.6 5.8.7 5.9 5.9.2 5.9.3 5.9.4 5.9.5 5.9.6 5.9.7 5.9.8 6.0 6.0.1 6.0.2 6.0.3 6.0.4 6.0.5 6.0.6 6.1 6.1.1 6.1.2 6.1.3 6.1.4 6.1.5 trunk 1.1 1.10 1.10.0.1 1.10.1 1.2 1.3 1.3.1 1.3.2 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.5 1.6 1.6.1 1.7 1.7.1 1.7.2 1.7.4 1.7.5 1.7.6 1.7.6.1 1.7.7 1.7.7.1 1.7.8 1.8 1.8.0.1 1.8.0.2 1.8.0.3 1.8.0.4 1.8.1 1.8.1.1 1.9 1.9.1 1.9.2 1.9.2.1 1.9.2.2 1.9.3 1.9.4 1.9.5 1.9.5.1 2.0 2.0-beta 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.1 2.1.1 2.1.2 2.2 2.2.1 2.3 2.3.1 2.4 2.4.1 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 3.0 3.0-beta 3.0.1 3.0.2 3.0.2.1 3.1 3.1.1 3.1.2 3.2 3.2.1 3.3 3.3.1 3.3.2 3.3.3 3.4 3.4.1 3.4.2 3.5 3.5.1 3.5.2 3.5.3 3.5.4 3.6 3.7 3.7.1 3.7.2 3.8 3.8.1 3.9 3.9-beta 3.9.1 3.9.2 3.9.3 4.0 4.0.1 4.0.2 4.0.3 4.1 4.1-beta 4.1.1 4.1.2 4.2 4.2-beta 4.2.1 4.2.2 4.3 4.3.1 4.4 4.4.1 4.4.2 4.5 4.5.1 4.6 4.6.1 4.7 4.8 4.8.1 4.9 4.9.1 4.9.2 5.0 5.0.1
contact-form-7 / includes / formatting.php
contact-form-7 / includes Last commit date
block-editor 4 years ago css 4 years ago js 4 years ago capabilities.php 7 years ago config-validator.php 4 years ago contact-form-functions.php 4 years ago contact-form-template.php 5 years ago contact-form.php 4 years ago controller.php 5 years ago file.php 4 years ago form-tag.php 4 years ago form-tags-manager.php 4 years ago formatting.php 4 years ago functions.php 4 years ago integration.php 4 years ago l10n.php 5 years ago mail.php 4 years ago pipe.php 4 years ago rest-api.php 4 years ago shortcodes.php 9 years ago special-mail-tags.php 5 years ago submission.php 4 years ago upgrade.php 7 years ago validation-functions.php 4 years ago validation.php 7 years ago
formatting.php
549 lines
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 '';
17 }
18
19 $pee = $pee . "\n"; // just to make things a little easier, pad the end
20 $pee = preg_replace( '|<br />\s*<br />|', "\n\n", $pee );
21 // Space things out a little
22 /* wpcf7: remove select and input */
23 $allblocks = '(?:table|thead|tfoot|caption|col|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|form|map|area|blockquote|address|math|style|p|h[1-6]|hr|fieldset|legend|section|article|aside|hgroup|header|footer|nav|figure|figcaption|details|menu|summary)';
24 $pee = preg_replace( '!(<' . $allblocks . '[^>]*>)!', "\n$1", $pee );
25 $pee = preg_replace( '!(</' . $allblocks . '>)!', "$1\n\n", $pee );
26
27 /* wpcf7: take care of [response], [recaptcha], and [hidden] tags */
28 $form_tags_manager = WPCF7_FormTagsManager::get_instance();
29 $block_hidden_form_tags = $form_tags_manager->collect_tag_types(
30 array( 'display-block', 'display-hidden' ) );
31 $block_hidden_form_tags = sprintf( '(?:%s)',
32 implode( '|', $block_hidden_form_tags ) );
33
34 $pee = preg_replace( '!(\[' . $block_hidden_form_tags . '[^]]*\])!',
35 "\n$1\n\n", $pee );
36
37 $pee = str_replace( array( "\r\n", "\r" ), "\n", $pee ); // cross-platform newlines
38
39 if ( strpos( $pee, '<object' ) !== false ) {
40 $pee = preg_replace( '|\s*<param([^>]*)>\s*|', "<param$1>", $pee ); // no pee inside object/embed
41 $pee = preg_replace( '|\s*</embed>\s*|', '</embed>', $pee );
42 }
43
44 $pee = preg_replace( "/\n\n+/", "\n\n", $pee ); // take care of duplicates
45 // make paragraphs, including one at the end
46 $pees = preg_split( '/\n\s*\n/', $pee, -1, PREG_SPLIT_NO_EMPTY );
47 $pee = '';
48
49 foreach ( $pees as $tinkle ) {
50 $pee .= '<p>' . trim( $tinkle, "\n" ) . "</p>\n";
51 }
52
53 $pee = preg_replace( '!<p>([^<]+)</(div|address|form|fieldset)>!', "<p>$1</p></$2>", $pee );
54
55 $pee = preg_replace( '|<p>\s*</p>|', '', $pee ); // under certain strange conditions it could create a P of entirely whitespace
56
57 $pee = preg_replace( '!<p>\s*(</?' . $allblocks . '[^>]*>)\s*</p>!', "$1", $pee ); // don't pee all over a tag
58 $pee = preg_replace( "|<p>(<li.+?)</p>|", "$1", $pee ); // problem with nested lists
59 $pee = preg_replace( '|<p><blockquote([^>]*)>|i', "<blockquote$1><p>", $pee );
60 $pee = str_replace( '</blockquote></p>', '</p></blockquote>', $pee );
61 $pee = preg_replace( '!<p>\s*(</?' . $allblocks . '[^>]*>)!', "$1", $pee );
62 $pee = preg_replace( '!(</?' . $allblocks . '[^>]*>)\s*</p>!', "$1", $pee );
63
64 /* wpcf7: take care of [response], [recaptcha], and [hidden] tag */
65 $pee = preg_replace( '!<p>\s*(\[' . $block_hidden_form_tags . '[^]]*\])!',
66 "$1", $pee );
67 $pee = preg_replace( '!(\[' . $block_hidden_form_tags . '[^]]*\])\s*</p>!',
68 "$1", $pee );
69
70 if ( $br ) {
71 /* wpcf7: add textarea */
72 $pee = preg_replace_callback(
73 '/<(script|style|textarea).*?<\/\\1>/s',
74 'wpcf7_autop_preserve_newline_callback', $pee );
75 $pee = preg_replace( '|(?<!<br />)\s*\n|', "<br />\n", $pee ); // optionally make line breaks
76 $pee = str_replace( '<WPPreserveNewline />', "\n", $pee );
77
78 /* wpcf7: remove extra <br /> just added before [response], [recaptcha], and [hidden] tags */
79 $pee = preg_replace( '!<br />\n(\[' . $block_hidden_form_tags . '[^]]*\])!',
80 "\n$1", $pee );
81 }
82
83 $pee = preg_replace( '!(</?' . $allblocks . '[^>]*>)\s*<br />!', "$1", $pee );
84 $pee = preg_replace( '!<br />(\s*</?(?:p|li|div|dl|dd|dt|th|pre|td|ul|ol)[^>]*>)!', '$1', $pee );
85
86 if ( strpos( $pee, '<pre' ) !== false ) {
87 $pee = preg_replace_callback( '!(<pre[^>]*>)(.*?)</pre>!is',
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 );
118
119 if ( false !== strpos( $text, '<' ) ) {
120 $text = wp_pre_kses_less_than( $text );
121 $text = wp_strip_all_tags( $text );
122 }
123
124 $text = preg_replace( '/%[a-f0-9]{2}/i', '', $text );
125 $text = preg_replace( '/ +/', ' ', $text );
126 $text = trim( $text, ' ' );
127
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
141 if ( preg_match( '/^"(.*)"$/s', $text, $matches ) ) {
142 $text = $matches[1];
143 } elseif ( preg_match( "/^'(.*)'$/s", $text, $matches ) ) {
144 $text = $matches[1];
145 }
146
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 );
161 }
162
163 if ( is_array( $arr ) ) {
164 $result = array();
165
166 foreach ( $arr as $key => $text ) {
167 $result[$key] = wpcf7_strip_quote_deep( $text );
168 }
169
170 return $result;
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;
185 }
186
187 $nls = array( "\r\n", "\r", "\n" );
188
189 if ( ! in_array( $to, $nls ) ) {
190 return $text;
191 }
192
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();
208
209 foreach ( $arr as $key => $text ) {
210 $result[$key] = wpcf7_normalize_newline_deep( $text, $to );
211 }
212
213 return $result;
214 }
215
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
321 $filename = preg_replace( '/[\r\n\t -]+/', '-', $filename );
322 $filename = preg_replace( '/[\pC\pZ]+/iu', '', $filename );
323
324 $parts = explode( '.', $filename );
325
326 if ( count( $parts ) < 2 ) {
327 return $filename;
328 }
329
330 $script_pattern = '/^(php|phtml|pl|py|rb|cgi|asp|aspx)\d?$/i';
331
332 $filename = array_shift( $parts );
333 $extension = array_pop( $parts );
334
335 foreach ( (array) $parts as $part ) {
336 if ( preg_match( $script_pattern, $part ) ) {
337 $filename .= '.' . $part . '_';
338 } else {
339 $filename .= '.' . $part;
340 }
341 }
342
343 if ( preg_match( $script_pattern, $extension ) ) {
344 $filename .= '.' . $extension . '_.txt';
345 } else {
346 $filename .= '.' . $extension;
347 }
348
349 return $filename;
350 }
351
352
353 /**
354 * Masks a password with asterisks (*).
355 *
356 * @param int $right Length of right-hand unmasked text. Default 0.
357 * @param int $left Length of left-hand unmasked text. Default 0.
358 * @return string Text of masked password.
359 */
360 function wpcf7_mask_password( $text, $right = 0, $left = 0 ) {
361 $length = strlen( $text );
362
363 $right = absint( $right );
364 $left = absint( $left );
365
366 if ( $length < $right + $left ) {
367 $right = $left = 0;
368 }
369
370 if ( $length <= 48 ) {
371 $masked = str_repeat( '*', $length - ( $right + $left ) );
372 } elseif ( $right + $left < 48 ) {
373 $masked = str_repeat( '*', 48 - ( $right + $left ) );
374 } else {
375 $masked = '****';
376 }
377
378 $left_unmasked = $left ? substr( $text, 0, $left ) : '';
379 $right_unmasked = $right ? substr( $text, -1 * $right ) : '';
380
381 $text = $left_unmasked . $masked . $right_unmasked;
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 }
549