PluginProbe ʕ •ᴥ•ʔ
Contact Form 7 / 6.0.1
Contact Form 7 v6.0.1
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 1 year ago config-validator 1 year ago css 2 years ago js 1 year ago swv 1 year ago capabilities.php 7 years ago contact-form-functions.php 1 year ago contact-form-template.php 2 years ago contact-form.php 1 year ago controller.php 1 year ago file.php 1 year ago form-tag.php 2 years ago form-tags-manager.php 3 years ago formatting.php 1 year ago functions.php 1 year ago html-formatter.php 1 year ago integration.php 2 years ago l10n.php 3 years ago mail-tag.php 2 years ago mail.php 1 year ago pipe.php 2 years ago pocket-holder.php 3 years ago rest-api.php 2 years ago shortcodes.php 3 years ago special-mail-tags.php 1 year ago submission.php 1 year ago upgrade.php 2 years ago validation-functions.php 1 year ago validation.php 3 years ago
formatting.php
613 lines
1 <?php
2
3 /**
4 * Replaces double line breaks with paragraph elements.
5 *
6 * @param string $input The text which has to be formatted.
7 * @param bool $br Optional. If set, this will convert all remaining
8 * line breaks after paragraphing. Default true.
9 * @return string Text which has been converted into correct paragraph tags.
10 */
11 function wpcf7_autop( $input, $br = true ) {
12 $placeholders = array();
13
14 // Replace non-HTML embedded elements with placeholders.
15 $input = preg_replace_callback(
16 '/<(math|svg).*?<\/\1>/is',
17 static function ( $matches ) use ( &$placeholders ) {
18 $placeholder = sprintf(
19 '<%1$s id="%2$s" />',
20 WPCF7_HTMLFormatter::placeholder_inline,
21 sha1( $matches[0] )
22 );
23
24 list( $placeholder ) =
25 WPCF7_HTMLFormatter::normalize_start_tag( $placeholder );
26
27 $placeholders[$placeholder] = $matches[0];
28
29 return $placeholder;
30 },
31 $input
32 );
33
34 $formatter = new WPCF7_HTMLFormatter( array(
35 'auto_br' => $br,
36 ) );
37
38 $chunks = $formatter->separate_into_chunks( $input );
39
40 $output = $formatter->format( $chunks );
41
42 // Restore from placeholders.
43 $output = str_replace(
44 array_keys( $placeholders ),
45 array_values( $placeholders ),
46 $output
47 );
48
49 return $output;
50 }
51
52
53 /**
54 * Newline preservation help function for wpcf7_autop().
55 *
56 * @deprecated 5.7 Unnecessary to use any more.
57 *
58 * @param array $matches preg_replace_callback() matches array.
59 * @return string Text including newline placeholders.
60 */
61 function wpcf7_autop_preserve_newline_callback( $matches ) {
62 return str_replace( "\n", '<WPPreserveNewline />', $matches[0] );
63 }
64
65
66 /**
67 * Sanitizes the query variables.
68 *
69 * @param string $text Query variable.
70 * @return string Text sanitized.
71 */
72 function wpcf7_sanitize_query_var( $text ) {
73 $text = wp_unslash( $text );
74 $text = wp_check_invalid_utf8( $text );
75
76 if ( false !== strpos( $text, '<' ) ) {
77 $text = wp_pre_kses_less_than( $text );
78 $text = wp_strip_all_tags( $text );
79 }
80
81 $text = preg_replace( '/%[a-f0-9]{2}/i', '', $text );
82 $text = preg_replace( '/ +/', ' ', $text );
83 $text = trim( $text, ' ' );
84
85 return $text;
86 }
87
88
89 /**
90 * Strips quote characters surrounding the input.
91 *
92 * @param string $text Input text.
93 * @return string Processed output.
94 */
95 function wpcf7_strip_quote( $text ) {
96 $text = trim( $text );
97
98 if ( preg_match( '/^"(.*)"$/s', $text, $matches ) ) {
99 $text = $matches[1];
100 } elseif ( preg_match( "/^'(.*)'$/s", $text, $matches ) ) {
101 $text = $matches[1];
102 }
103
104 return $text;
105 }
106
107
108 /**
109 * Navigates through an array, object, or scalar, and
110 * strips quote characters surrounding the each value.
111 *
112 * @param mixed $input The array or string to be processed.
113 * @return mixed Processed value.
114 */
115 function wpcf7_strip_quote_deep( $input ) {
116 if ( is_string( $input ) ) {
117 return wpcf7_strip_quote( $input );
118 }
119
120 if ( is_array( $input ) ) {
121 $result = array();
122
123 foreach ( $input as $key => $text ) {
124 $result[$key] = wpcf7_strip_quote_deep( $text );
125 }
126
127 return $result;
128 }
129 }
130
131
132 /**
133 * Normalizes newline characters.
134 *
135 * @param string $text Input text.
136 * @param string $to Optional. The newline character that is used in the output.
137 * @return string Normalized text.
138 */
139 function wpcf7_normalize_newline( $text, $to = "\n" ) {
140 if ( ! is_string( $text ) ) {
141 return $text;
142 }
143
144 $nls = array( "\r\n", "\r", "\n" );
145
146 if ( ! in_array( $to, $nls ) ) {
147 return $text;
148 }
149
150 return str_replace( $nls, $to, $text );
151 }
152
153
154 /**
155 * Navigates through an array, object, or scalar, and
156 * normalizes newline characters in the each value.
157 *
158 * @param mixed $input The array or string to be processed.
159 * @param string $to Optional. The newline character that is used in the output.
160 * @return mixed Processed value.
161 */
162 function wpcf7_normalize_newline_deep( $input, $to = "\n" ) {
163 if ( is_array( $input ) ) {
164 $result = array();
165
166 foreach ( $input as $key => $text ) {
167 $result[$key] = wpcf7_normalize_newline_deep( $text, $to );
168 }
169
170 return $result;
171 }
172
173 return wpcf7_normalize_newline( $input, $to );
174 }
175
176
177 /**
178 * Strips newline characters.
179 *
180 * @param string $text Input text.
181 * @return string Processed one-line text.
182 */
183 function wpcf7_strip_newline( $text ) {
184 $text = (string) $text;
185 $text = str_replace( array( "\r", "\n" ), '', $text );
186 return trim( $text );
187 }
188
189
190 /**
191 * Canonicalizes text.
192 *
193 * @param string $text Input text.
194 * @param string|array|object $options Options.
195 * @return string Canonicalized text.
196 */
197 function wpcf7_canonicalize( $text, $options = '' ) {
198 // for back-compat
199 if ( is_string( $options ) and '' !== $options
200 and false === strpos( $options, '=' ) ) {
201 $options = array(
202 'strto' => $options,
203 );
204 }
205
206 $options = wp_parse_args( $options, array(
207 'strto' => 'lower',
208 'strip_separators' => false,
209 ) );
210
211 static $charset = null;
212
213 if ( ! isset( $charset ) ) {
214 $charset = get_option( 'blog_charset' );
215
216 $is_utf8 = in_array(
217 $charset,
218 array( 'utf8', 'utf-8', 'UTF8', 'UTF-8' )
219 );
220
221 if ( $is_utf8 ) {
222 $charset = 'UTF-8';
223 }
224 }
225
226 $text = html_entity_decode( $text, ENT_QUOTES | ENT_HTML5, $charset );
227
228 if ( function_exists( 'mb_convert_kana' ) ) {
229 $text = mb_convert_kana( $text, 'asKV', $charset );
230 }
231
232 if ( $options['strip_separators'] ) {
233 $text = preg_replace( '/[\r\n\t ]+/', '', $text );
234 } else {
235 $text = preg_replace( '/[\r\n\t ]+/', ' ', $text );
236 }
237
238 if ( 'lower' == $options['strto'] ) {
239 if ( function_exists( 'mb_strtolower' ) ) {
240 $text = mb_strtolower( $text, $charset );
241 } else {
242 $text = strtolower( $text );
243 }
244 } elseif ( 'upper' == $options['strto'] ) {
245 if ( function_exists( 'mb_strtoupper' ) ) {
246 $text = mb_strtoupper( $text, $charset );
247 } else {
248 $text = strtoupper( $text );
249 }
250 }
251
252 $text = trim( $text );
253 return $text;
254 }
255
256
257 /**
258 * Returns a canonical keyword usable for a name or an ID purposes.
259 */
260 function wpcf7_canonicalize_name( $text ) {
261 return preg_replace( '/[^0-9a-z]+/i', '-', $text );
262 }
263
264
265 /**
266 * Sanitizes Contact Form 7's form unit-tag.
267 *
268 * @param string $tag Unit-tag.
269 * @return string Sanitized unit-tag.
270 */
271 function wpcf7_sanitize_unit_tag( $tag ) {
272 $tag = preg_replace( '/[^A-Za-z0-9_-]/', '', (string) $tag );
273 return $tag;
274 }
275
276
277 /**
278 * Converts a file name to one that is not executable as a script.
279 *
280 * @param string $filename File name.
281 * @return string Converted file name.
282 */
283 function wpcf7_antiscript_file_name( $filename ) {
284 $filename = wp_basename( $filename );
285
286 // Apply part of protection logic from sanitize_file_name().
287 $filename = str_replace(
288 array(
289 '?', '[', ']', '/', '\\', '=', '<', '>', ':', ';', ',', "'", '"',
290 '&', '$', '#', '*', '(', ')', '|', '~', '`', '!', '{', '}',
291 '%', '+', '', '«', '»', '', '', chr( 0 )
292 ),
293 '',
294 $filename
295 );
296
297 $filename = preg_replace( '/[\r\n\t -]+/', '-', $filename );
298 $filename = preg_replace( '/[\pC\pZ]+/iu', '', $filename );
299
300 $parts = explode( '.', $filename );
301
302 if ( count( $parts ) < 2 ) {
303 return $filename;
304 }
305
306 $script_pattern = '/^(php|phtml|pl|py|rb|cgi|asp|aspx)\d?$/i';
307
308 $filename = array_shift( $parts );
309 $extension = array_pop( $parts );
310
311 foreach ( (array) $parts as $part ) {
312 if ( preg_match( $script_pattern, $part ) ) {
313 $filename .= '.' . $part . '_';
314 } else {
315 $filename .= '.' . $part;
316 }
317 }
318
319 if ( preg_match( $script_pattern, $extension ) ) {
320 $filename .= '.' . $extension . '_.txt';
321 } else {
322 $filename .= '.' . $extension;
323 }
324
325 return $filename;
326 }
327
328
329 /**
330 * Masks a password with asterisks (*).
331 *
332 * @param int $right Length of right-hand unmasked text. Default 0.
333 * @param int $left Length of left-hand unmasked text. Default 0.
334 * @return string Text of masked password.
335 */
336 function wpcf7_mask_password( $text, $right = 0, $left = 0 ) {
337 $length = strlen( $text );
338
339 $right = absint( $right );
340 $left = absint( $left );
341
342 if ( $length < $right + $left ) {
343 $right = $left = 0;
344 }
345
346 if ( $length <= 48 ) {
347 $masked = str_repeat( '*', $length - ( $right + $left ) );
348 } elseif ( $right + $left < 48 ) {
349 $masked = str_repeat( '*', 48 - ( $right + $left ) );
350 } else {
351 $masked = '****';
352 }
353
354 $left_unmasked = $left ? substr( $text, 0, $left ) : '';
355 $right_unmasked = $right ? substr( $text, -1 * $right ) : '';
356
357 $text = $left_unmasked . $masked . $right_unmasked;
358
359 return $text;
360 }
361
362
363 /**
364 * Returns an array of allowed HTML tags and attributes for a given context.
365 *
366 * @param string $context Context used to decide allowed tags and attributes.
367 * @return array Array of allowed HTML tags and their allowed attributes.
368 */
369 function wpcf7_kses_allowed_html( $context = 'form' ) {
370 static $allowed_tags = array();
371
372 if ( isset( $allowed_tags[$context] ) ) {
373 return apply_filters(
374 'wpcf7_kses_allowed_html',
375 $allowed_tags[$context],
376 $context
377 );
378 }
379
380 $allowed_tags[$context] = wp_kses_allowed_html( 'post' );
381
382 if ( 'form' === $context ) {
383 $additional_tags_for_form = array(
384 'button' => array(
385 'disabled' => true,
386 'name' => true,
387 'type' => true,
388 'value' => true,
389 ),
390 'datalist' => array(),
391 'fieldset' => array(
392 'disabled' => true,
393 'name' => true,
394 ),
395 'input' => array(
396 'accept' => true,
397 'alt' => true,
398 'capture' => true,
399 'checked' => true,
400 'disabled' => true,
401 'list' => true,
402 'max' => true,
403 'maxlength' => true,
404 'min' => true,
405 'minlength' => true,
406 'multiple' => true,
407 'name' => true,
408 'placeholder' => true,
409 'readonly' => true,
410 'size' => true,
411 'step' => true,
412 'type' => true,
413 'value' => true,
414 ),
415 'label' => array(
416 'for' => true,
417 ),
418 'legend' => array(),
419 'meter' => array(
420 'value' => true,
421 'min' => true,
422 'max' => true,
423 'low' => true,
424 'high' => true,
425 'optimum' => true,
426 ),
427 'optgroup' => array(
428 'disabled' => true,
429 'label' => true,
430 ),
431 'option' => array(
432 'disabled' => true,
433 'label' => true,
434 'selected' => true,
435 'value' => true,
436 ),
437 'output' => array(
438 'for' => true,
439 'name' => true,
440 ),
441 'progress' => array(
442 'max' => true,
443 'value' => true,
444 ),
445 'select' => array(
446 'disabled' => true,
447 'multiple' => true,
448 'name' => true,
449 'size' => true,
450 ),
451 'textarea' => array(
452 'cols' => true,
453 'disabled' => true,
454 'maxlength' => true,
455 'minlength' => true,
456 'name' => true,
457 'placeholder' => true,
458 'readonly' => true,
459 'rows' => true,
460 'spellcheck' => true,
461 'wrap' => true,
462 ),
463 );
464
465 $additional_tags_for_form = array_map(
466 static function ( $elm ) {
467 $global_attributes = array(
468 'aria-atomic' => true,
469 'aria-checked' => true,
470 'aria-describedby' => true,
471 'aria-details' => true,
472 'aria-disabled' => true,
473 'aria-hidden' => true,
474 'aria-invalid' => true,
475 'aria-label' => true,
476 'aria-labelledby' => true,
477 'aria-live' => true,
478 'aria-relevant' => true,
479 'aria-required' => true,
480 'aria-selected' => true,
481 'class' => true,
482 'data-*' => true,
483 'id' => true,
484 'inputmode' => true,
485 'role' => true,
486 'style' => true,
487 'tabindex' => true,
488 'title' => true,
489 );
490
491 return array_merge( $global_attributes, (array) $elm );
492 },
493 $additional_tags_for_form
494 );
495
496 $allowed_tags[$context] = array_merge(
497 $allowed_tags[$context],
498 $additional_tags_for_form
499 );
500 }
501
502 return apply_filters(
503 'wpcf7_kses_allowed_html',
504 $allowed_tags[$context],
505 $context
506 );
507 }
508
509
510 /**
511 * Sanitizes content for allowed HTML tags for the specified context.
512 *
513 * @param string $input Content to filter.
514 * @param string $context Context used to decide allowed tags and attributes.
515 * @return string Filtered text with allowed HTML tags and attributes intact.
516 */
517 function wpcf7_kses( $input, $context = 'form' ) {
518 $output = wp_kses(
519 $input,
520 wpcf7_kses_allowed_html( $context )
521 );
522
523 return $output;
524 }
525
526
527 /**
528 * Returns a formatted string of HTML attributes.
529 *
530 * @param array $atts Associative array of attribute name and value pairs.
531 * @return string Formatted HTML attributes.
532 */
533 function wpcf7_format_atts( $atts ) {
534 $atts_filtered = array();
535
536 foreach ( $atts as $name => $value ) {
537 $name = strtolower( trim( $name ) );
538
539 if ( ! preg_match( '/^[a-z_:][a-z_:.0-9-]*$/', $name ) ) {
540 continue;
541 }
542
543 static $boolean_attributes = array(
544 'checked',
545 'disabled',
546 'inert',
547 'multiple',
548 'readonly',
549 'required',
550 'selected',
551 );
552
553 if ( in_array( $name, $boolean_attributes ) and '' === $value ) {
554 $value = false;
555 }
556
557 if ( is_numeric( $value ) ) {
558 $value = (string) $value;
559 }
560
561 if ( null === $value or false === $value ) {
562 unset( $atts_filtered[$name] );
563 } elseif ( true === $value ) {
564 $atts_filtered[$name] = $name; // boolean attribute
565 } elseif ( is_string( $value ) ) {
566 $atts_filtered[$name] = trim( $value );
567 }
568 }
569
570 $output = '';
571
572 foreach ( $atts_filtered as $name => $value ) {
573 $output .= sprintf( ' %1$s="%2$s"', $name, esc_attr( $value ) );
574 }
575
576 return trim( $output );
577 }
578
579
580 /**
581 * Strips surrounding whitespaces.
582 *
583 * @link https://contactform7.com/2024/07/13/consistent-handling-policy-of-surrounding-whitespaces/
584 *
585 * @param string|array $input Input text.
586 * @return string|array Output text.
587 */
588 function wpcf7_strip_whitespaces( $input ) {
589 if ( is_array( $input ) ) {
590 return array_map( 'wpcf7_strip_whitespaces', $input );
591 }
592
593 // https://www.unicode.org/Public/UCD/latest/ucd/PropList.txt
594 // https://tc39.es/ecma262/multipage/ecmascript-language-lexical-grammar.html
595 $whitespaces = '\x09-\x0D\x20\x85\xA0\x{1680}\x{2000}-\x{200A}\x{2028}\x{2029}\x{202F}\x{205F}\x{3000}\x{FEFF}';
596
597 // Strip leading whitespaces
598 $input = preg_replace(
599 sprintf( '/^[%s]+/u', $whitespaces ),
600 '',
601 $input
602 );
603
604 // Strip trailing whitespaces
605 $input = preg_replace(
606 sprintf( '/[%s]+$/u', $whitespaces ),
607 '',
608 $input
609 );
610
611 return $input;
612 }
613