PluginProbe ʕ •ᴥ•ʔ
Contact Form 7 / 5.7.3
Contact Form 7 v5.7.3
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 / functions.php
contact-form-7 / includes Last commit date
block-editor 3 years ago css 3 years ago js 3 years ago swv 3 years ago capabilities.php 7 years ago config-validator.php 3 years ago contact-form-functions.php 3 years ago contact-form-template.php 3 years ago contact-form.php 3 years ago controller.php 3 years ago file.php 3 years ago form-tag.php 3 years ago form-tags-manager.php 3 years ago formatting.php 3 years ago functions.php 3 years ago html-formatter.php 3 years ago integration.php 3 years ago l10n.php 3 years ago mail.php 3 years ago pipe.php 4 years ago pocket-holder.php 3 years ago rest-api.php 4 years ago shortcodes.php 3 years ago special-mail-tags.php 3 years ago submission.php 3 years ago upgrade.php 7 years ago validation-functions.php 3 years ago validation.php 3 years ago
functions.php
738 lines
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
23 if ( is_ssl()
24 and 'http:' == substr( $url, 0, 5 ) ) {
25 $url = 'https:' . substr( $url, 5 );
26 }
27
28 return $url;
29 }
30
31
32 /**
33 * Include a file under WPCF7_PLUGIN_MODULES_DIR.
34 *
35 * @param string $path File path relative to the module dir.
36 * @return bool True on success, false on failure.
37 */
38 function wpcf7_include_module_file( $path ) {
39 $dir = WPCF7_PLUGIN_MODULES_DIR;
40
41 if ( empty( $dir ) or ! is_dir( $dir ) ) {
42 return false;
43 }
44
45 $path = path_join( $dir, ltrim( $path, '/' ) );
46
47 if ( file_exists( $path ) ) {
48 include_once $path;
49 return true;
50 }
51
52 return false;
53 }
54
55
56 /**
57 * Retrieves uploads directory information.
58 *
59 * @param string|bool $type Optional. Type of output. Default false.
60 * @return array|string Information about the upload directory.
61 */
62 function wpcf7_upload_dir( $type = false ) {
63 $uploads = wp_get_upload_dir();
64
65 $uploads = apply_filters( 'wpcf7_upload_dir', array(
66 'dir' => $uploads['basedir'],
67 'url' => $uploads['baseurl'],
68 ) );
69
70 if ( 'dir' == $type ) {
71 return $uploads['dir'];
72 } if ( 'url' == $type ) {
73 return $uploads['url'];
74 }
75
76 return $uploads;
77 }
78
79
80 /**
81 * Verifies that a correct security nonce was used with time limit.
82 *
83 * @param string $nonce Nonce value that was used for verification.
84 * @param string $action Optional. Context to what is taking place.
85 * Default 'wp_rest'.
86 * @return int|bool 1 if the nonce is generated between 0-12 hours ago,
87 * 2 if the nonce is generated between 12-24 hours ago.
88 * False if the nonce is invalid.
89 */
90 function wpcf7_verify_nonce( $nonce, $action = 'wp_rest' ) {
91 return wp_verify_nonce( $nonce, $action );
92 }
93
94
95 /**
96 * Creates a cryptographic token tied to a specific action, user, user session,
97 * and window of time.
98 *
99 * @param string $action Optional. Context to what is taking place.
100 * Default 'wp_rest'.
101 * @return string The token.
102 */
103 function wpcf7_create_nonce( $action = 'wp_rest' ) {
104 return wp_create_nonce( $action );
105 }
106
107
108 /**
109 * Converts multi-dimensional array to a flat array.
110 *
111 * @param mixed $input Array or item of array.
112 * @return array Flatten array.
113 */
114 function wpcf7_array_flatten( $input ) {
115 if ( ! is_array( $input ) ) {
116 return array( $input );
117 }
118
119 $output = array();
120
121 foreach ( $input as $value ) {
122 $output = array_merge( $output, wpcf7_array_flatten( $value ) );
123 }
124
125 return $output;
126 }
127
128
129 /**
130 * Excludes unset or blank text values from the given array.
131 *
132 * @param array $input The array.
133 * @return array Array without blank text values.
134 */
135 function wpcf7_exclude_blank( $input ) {
136 $output = array_filter( $input,
137 function ( $i ) {
138 return isset( $i ) && '' !== $i;
139 }
140 );
141
142 return array_values( $output );
143 }
144
145
146 /**
147 * Creates a comma-separated list from a multi-dimensional array.
148 *
149 * @param mixed $input Array or item of array.
150 * @param string|array $args Optional. Output options.
151 * @return string Comma-separated list.
152 */
153 function wpcf7_flat_join( $input, $args = '' ) {
154 $args = wp_parse_args( $args, array(
155 'separator' => ', ',
156 ) );
157
158 $input = wpcf7_array_flatten( $input );
159 $output = array();
160
161 foreach ( (array) $input as $value ) {
162 if ( is_scalar( $value ) ) {
163 $output[] = trim( (string) $value );
164 }
165 }
166
167 return implode( $args['separator'], $output );
168 }
169
170
171 /**
172 * Returns true if HTML5 is supported.
173 */
174 function wpcf7_support_html5() {
175 return (bool) wpcf7_apply_filters_deprecated(
176 'wpcf7_support_html5',
177 array( true ),
178 '5.6',
179 ''
180 );
181 }
182
183
184 /**
185 * Returns true if HTML5 fallback is active.
186 */
187 function wpcf7_support_html5_fallback() {
188 return (bool) apply_filters( 'wpcf7_support_html5_fallback', false );
189 }
190
191
192 /**
193 * Returns true if the Really Simple CAPTCHA plugin is used for contact forms.
194 */
195 function wpcf7_use_really_simple_captcha() {
196 return apply_filters( 'wpcf7_use_really_simple_captcha',
197 WPCF7_USE_REALLY_SIMPLE_CAPTCHA
198 );
199 }
200
201
202 /**
203 * Returns true if config validation is active.
204 */
205 function wpcf7_validate_configuration() {
206 return apply_filters( 'wpcf7_validate_configuration',
207 WPCF7_VALIDATE_CONFIGURATION
208 );
209 }
210
211
212 /**
213 * Returns true if wpcf7_autop() is applied to form content.
214 */
215 function wpcf7_autop_or_not() {
216 return (bool) apply_filters( 'wpcf7_autop_or_not', WPCF7_AUTOP );
217 }
218
219
220 /**
221 * Returns true if JavaScript for this plugin is loaded.
222 */
223 function wpcf7_load_js() {
224 return apply_filters( 'wpcf7_load_js', WPCF7_LOAD_JS );
225 }
226
227
228 /**
229 * Returns true if CSS for this plugin is loaded.
230 */
231 function wpcf7_load_css() {
232 return apply_filters( 'wpcf7_load_css', WPCF7_LOAD_CSS );
233 }
234
235
236 /**
237 * Returns a formatted string of HTML attributes.
238 *
239 * @param array $atts Associative array of attribute name and value pairs.
240 * @return string Formatted HTML attributes.
241 */
242 function wpcf7_format_atts( $atts ) {
243 $atts_filtered = array();
244
245 foreach ( $atts as $name => $value ) {
246 $name = strtolower( trim( $name ) );
247
248 if ( ! preg_match( '/^[a-z_:][a-z_:.0-9-]*$/', $name ) ) {
249 continue;
250 }
251
252 static $boolean_attributes = array(
253 'checked', 'disabled', 'multiple', 'readonly', 'required', 'selected',
254 );
255
256 if ( in_array( $name, $boolean_attributes ) and '' === $value ) {
257 $value = false;
258 }
259
260 if ( is_numeric( $value ) ) {
261 $value = (string) $value;
262 }
263
264 if ( null === $value or false === $value ) {
265 unset( $atts_filtered[$name] );
266 } elseif ( true === $value ) {
267 $atts_filtered[$name] = $name; // boolean attribute
268 } elseif ( is_string( $value ) ) {
269 $atts_filtered[$name] = trim( $value );
270 }
271 }
272
273 $output = '';
274
275 foreach ( $atts_filtered as $name => $value ) {
276 $output .= sprintf( ' %1$s="%2$s"', $name, esc_attr( $value ) );
277 }
278
279 return trim( $output );
280 }
281
282
283 /**
284 * Builds an HTML anchor element.
285 *
286 * @param string $url Link URL.
287 * @param string $anchor_text Anchor label text.
288 * @param string|array $args Optional. Link options.
289 * @return string Formatted anchor element.
290 */
291 function wpcf7_link( $url, $anchor_text, $args = '' ) {
292 $args = wp_parse_args( $args, array(
293 'id' => null,
294 'class' => null,
295 ) );
296
297 $atts = array_merge( $args, array(
298 'href' => esc_url( $url ),
299 ) );
300
301 return sprintf(
302 '<a %1$s>%2$s</a>',
303 wpcf7_format_atts( $atts ),
304 esc_html( $anchor_text )
305 );
306 }
307
308
309 /**
310 * Returns the current request URL.
311 */
312 function wpcf7_get_request_uri() {
313 static $request_uri = '';
314
315 if ( empty( $request_uri ) ) {
316 $request_uri = add_query_arg( array() );
317 }
318
319 return sanitize_url( $request_uri );
320 }
321
322
323 /**
324 * Registers post types used for this plugin.
325 */
326 function wpcf7_register_post_types() {
327 if ( class_exists( 'WPCF7_ContactForm' ) ) {
328 WPCF7_ContactForm::register_post_type();
329 return true;
330 } else {
331 return false;
332 }
333 }
334
335
336 /**
337 * Returns the version string of this plugin.
338 *
339 * @param string|array $args Optional. Output options.
340 * @return string Version string.
341 */
342 function wpcf7_version( $args = '' ) {
343 $defaults = array(
344 'limit' => -1,
345 'only_major' => false,
346 );
347
348 $args = wp_parse_args( $args, $defaults );
349
350 if ( $args['only_major'] ) {
351 $args['limit'] = 2;
352 }
353
354 $args['limit'] = (int) $args['limit'];
355
356 $ver = WPCF7_VERSION;
357 $ver = strtr( $ver, '_-+', '...' );
358 $ver = preg_replace( '/[^0-9.]+/', ".$0.", $ver );
359 $ver = preg_replace( '/[.]+/', ".", $ver );
360 $ver = trim( $ver, '.' );
361 $ver = explode( '.', $ver );
362
363 if ( -1 < $args['limit'] ) {
364 $ver = array_slice( $ver, 0, $args['limit'] );
365 }
366
367 $ver = implode( '.', $ver );
368
369 return $ver;
370 }
371
372
373 /**
374 * Returns array entries that match the given version.
375 *
376 * @param string $version The version to search for.
377 * @param array $input Search target array.
378 * @return array|bool Array of matched entries. False on failure.
379 */
380 function wpcf7_version_grep( $version, array $input ) {
381 $pattern = '/^' . preg_quote( (string) $version, '/' ) . '(?:\.|$)/';
382
383 return preg_grep( $pattern, $input );
384 }
385
386
387 /**
388 * Returns an enctype attribute value.
389 *
390 * @param string $enctype Enctype value.
391 * @return string Enctype value. Empty if not a valid enctype.
392 */
393 function wpcf7_enctype_value( $enctype ) {
394 $enctype = trim( $enctype );
395
396 if ( empty( $enctype ) ) {
397 return '';
398 }
399
400 $valid_enctypes = array(
401 'application/x-www-form-urlencoded',
402 'multipart/form-data',
403 'text/plain',
404 );
405
406 if ( in_array( $enctype, $valid_enctypes ) ) {
407 return $enctype;
408 }
409
410 $pattern = '%^enctype="(' . implode( '|', $valid_enctypes ) . ')"$%';
411
412 if ( preg_match( $pattern, $enctype, $matches ) ) {
413 return $matches[1]; // for back-compat
414 }
415
416 return '';
417 }
418
419
420 /**
421 * Removes directory recursively.
422 *
423 * @param string $dir Directory path.
424 * @return bool True on success, false on failure.
425 */
426 function wpcf7_rmdir_p( $dir ) {
427 if ( is_file( $dir ) ) {
428 $file = $dir;
429
430 if ( @unlink( $file ) ) {
431 return true;
432 }
433
434 $stat = stat( $file );
435
436 if ( @chmod( $file, $stat['mode'] | 0200 ) ) { // add write for owner
437 if ( @unlink( $file ) ) {
438 return true;
439 }
440
441 @chmod( $file, $stat['mode'] );
442 }
443
444 return false;
445 }
446
447 if ( ! is_dir( $dir ) ) {
448 return false;
449 }
450
451 if ( $handle = opendir( $dir ) ) {
452 while ( false !== ( $file = readdir( $handle ) ) ) {
453 if ( $file == "."
454 or $file == ".." ) {
455 continue;
456 }
457
458 wpcf7_rmdir_p( path_join( $dir, $file ) );
459 }
460
461 closedir( $handle );
462 }
463
464 if ( false !== ( $files = scandir( $dir ) )
465 and ! array_diff( $files, array( '.', '..' ) ) ) {
466 return rmdir( $dir );
467 }
468
469 return false;
470 }
471
472
473 /**
474 * Builds a URL-encoded query string.
475 *
476 * @link https://developer.wordpress.org/reference/functions/_http_build_query/
477 *
478 * @param array $args URL query parameters.
479 * @param string $key Optional. If specified, used to prefix key name.
480 * @return string Query string.
481 */
482 function wpcf7_build_query( $args, $key = '' ) {
483 $sep = '&';
484 $ret = array();
485
486 foreach ( (array) $args as $k => $v ) {
487 $k = urlencode( $k );
488
489 if ( ! empty( $key ) ) {
490 $k = $key . '%5B' . $k . '%5D';
491 }
492
493 if ( null === $v ) {
494 continue;
495 } elseif ( false === $v ) {
496 $v = '0';
497 }
498
499 if ( is_array( $v ) or is_object( $v ) ) {
500 array_push( $ret, wpcf7_build_query( $v, $k ) );
501 } else {
502 array_push( $ret, $k . '=' . urlencode( $v ) );
503 }
504 }
505
506 return implode( $sep, $ret );
507 }
508
509
510 /**
511 * Returns the number of code units in a string.
512 *
513 * @link http://www.w3.org/TR/html5/infrastructure.html#code-unit-length
514 *
515 * @param string $text Input string.
516 * @return int|bool The number of code units, or false if
517 * mb_convert_encoding is not available.
518 */
519 function wpcf7_count_code_units( $text ) {
520 static $use_mb = null;
521
522 if ( is_null( $use_mb ) ) {
523 $use_mb = function_exists( 'mb_convert_encoding' );
524 }
525
526 if ( ! $use_mb ) {
527 return false;
528 }
529
530 $text = (string) $text;
531 $text = str_replace( "\r\n", "\n", $text );
532
533 $encoding = mb_detect_encoding( $text, mb_detect_order(), true );
534
535 if ( $encoding ) {
536 $text = mb_convert_encoding( $text, 'UTF-16', $encoding );
537 } else {
538 $text = mb_convert_encoding( $text, 'UTF-16', 'UTF-8' );
539 }
540
541 $byte_count = mb_strlen( $text, '8bit' );
542
543 return floor( $byte_count / 2 );
544 }
545
546
547 /**
548 * Returns true if WordPress is running on the localhost.
549 */
550 function wpcf7_is_localhost() {
551 $sitename = wp_parse_url( network_home_url(), PHP_URL_HOST );
552 return in_array( strtolower( $sitename ), array( 'localhost', '127.0.0.1' ) );
553 }
554
555
556 /**
557 * Marks a function as deprecated and informs when it has been used.
558 *
559 * @param string $function_name The function that was called.
560 * @param string $version The version of Contact Form 7 that deprecated
561 * the function.
562 * @param string $replacement The function that should have been called.
563 */
564 function wpcf7_deprecated_function( $function_name, $version, $replacement ) {
565 if ( WP_DEBUG ) {
566 if ( function_exists( '__' ) ) {
567 trigger_error(
568 sprintf(
569 /* translators: 1: PHP function name, 2: version number, 3: alternative function name */
570 __( 'Function %1$s is <strong>deprecated</strong> since Contact Form 7 version %2$s! Use %3$s instead.', 'contact-form-7' ),
571 $function_name, $version, $replacement
572 ),
573 E_USER_DEPRECATED
574 );
575 } else {
576 trigger_error(
577 sprintf(
578 'Function %1$s is <strong>deprecated</strong> since Contact Form 7 version %2$s! Use %3$s instead.',
579 $function_name, $version, $replacement
580 ),
581 E_USER_DEPRECATED
582 );
583 }
584 }
585 }
586
587
588 /**
589 * Fires functions attached to a deprecated filter hook.
590 *
591 * @param string $hook_name The name of the filter hook.
592 * @param array $args Array of additional function arguments to be
593 * passed to apply_filters().
594 * @param string $version The version of Contact Form 7 that deprecated
595 * the hook.
596 * @param string $replacement The hook that should have been used.
597 */
598 function wpcf7_apply_filters_deprecated( $hook_name, $args, $version, $replacement = '' ) {
599 if ( ! has_filter( $hook_name ) ) {
600 return $args[0];
601 }
602
603 if ( WP_DEBUG and apply_filters( 'deprecated_hook_trigger_error', true ) ) {
604 if ( $replacement ) {
605 trigger_error(
606 sprintf(
607 /* translators: 1: WordPress hook name, 2: version number, 3: alternative hook name */
608 __( 'Hook %1$s is <strong>deprecated</strong> since Contact Form 7 version %2$s! Use %3$s instead.', 'contact-form-7' ),
609 $hook_name,
610 $version,
611 $replacement
612 ),
613 E_USER_DEPRECATED
614 );
615 } else {
616 trigger_error(
617 sprintf(
618 /* translators: 1: WordPress hook name, 2: version number */
619 __( 'Hook %1$s is <strong>deprecated</strong> since Contact Form 7 version %2$s with no alternative available.', 'contact-form-7' ),
620 $hook_name,
621 $version
622 ),
623 E_USER_DEPRECATED
624 );
625 }
626 }
627
628 return apply_filters_ref_array( $hook_name, $args );
629 }
630
631
632 /**
633 * Marks something as being incorrectly called.
634 *
635 * @param string $function_name The function that was called.
636 * @param string $message A message explaining what has been done incorrectly.
637 * @param string $version The version of Contact Form 7 where the message
638 * was added.
639 */
640 function wpcf7_doing_it_wrong( $function_name, $message, $version ) {
641 if ( WP_DEBUG ) {
642 if ( function_exists( '__' ) ) {
643 if ( $version ) {
644 $version = sprintf(
645 /* translators: %s: Contact Form 7 version number. */
646 __( '(This message was added in Contact Form 7 version %s.)', 'contact-form-7' ),
647 $version
648 );
649 }
650
651 trigger_error(
652 sprintf(
653 /* translators: Developer debugging message. 1: PHP function name, 2: Explanatory message, 3: Contact Form 7 version number. */
654 __( 'Function %1$s was called incorrectly. %2$s %3$s', 'contact-form-7' ),
655 $function_name,
656 $message,
657 $version
658 ),
659 E_USER_NOTICE
660 );
661 } else {
662 if ( $version ) {
663 $version = sprintf(
664 '(This message was added in Contact Form 7 version %s.)',
665 $version
666 );
667 }
668
669 trigger_error(
670 sprintf(
671 'Function %1$s was called incorrectly. %2$s %3$s',
672 $function_name,
673 $message,
674 $version
675 ),
676 E_USER_NOTICE
677 );
678 }
679 }
680 }
681
682
683 /**
684 * Triggers an error about a remote HTTP request and response.
685 *
686 * @param string $url The resource URL.
687 * @param array $request Request arguments.
688 * @param array|WP_Error $response The response or WP_Error on failure.
689 */
690 function wpcf7_log_remote_request( $url, $request, $response ) {
691 $log = sprintf(
692 /* translators: 1: response code, 2: message, 3: body, 4: URL */
693 __( 'HTTP Response: %1$s %2$s %3$s from %4$s', 'contact-form-7' ),
694 (int) wp_remote_retrieve_response_code( $response ),
695 wp_remote_retrieve_response_message( $response ),
696 wp_remote_retrieve_body( $response ),
697 $url
698 );
699
700 $log = apply_filters( 'wpcf7_log_remote_request',
701 $log, $url, $request, $response
702 );
703
704 if ( $log ) {
705 trigger_error( $log );
706 }
707 }
708
709
710 /**
711 * Anonymizes an IP address by masking local part.
712 *
713 * @param string $ip_addr The original IP address.
714 * @return string|bool Anonymized IP address, or false on failure.
715 */
716 function wpcf7_anonymize_ip_addr( $ip_addr ) {
717 if ( ! function_exists( 'inet_ntop' )
718 or ! function_exists( 'inet_pton' ) ) {
719 return $ip_addr;
720 }
721
722 $packed = inet_pton( $ip_addr );
723
724 if ( false === $packed ) {
725 return $ip_addr;
726 }
727
728 if ( 4 == strlen( $packed ) ) { // IPv4
729 $mask = '255.255.255.0';
730 } elseif ( 16 == strlen( $packed ) ) { // IPv6
731 $mask = 'ffff:ffff:ffff:0000:0000:0000:0000:0000';
732 } else {
733 return $ip_addr;
734 }
735
736 return inet_ntop( $packed & inet_pton( $mask ) );
737 }
738