PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3
Jetpack – WP Security, Backup, Speed, & Growth v16.3
16.3 16.3-beta 16.3-a.5 16.3-a.7 16.3-a.3 16.3-a.1 16.2 16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 All 508 releases
← All changes | functions.global.php +559 -0 16.2-beta → 16.3 View file →
@@ -1,0 +1,559 @@
1 +<?php // phpcs:ignore WordPress.Files.FileName.NotHyphenatedLowercase
2 +/**
3 + * This file is meant to be the home for any generic & reusable functions
4 + * that can be accessed anywhere within Jetpack.
5 + *
6 + * This file is loaded whether Jetpack is active.
7 + *
8 + * Please namespace with jetpack_
9 + *
10 + * @package automattic/jetpack
11 + */
12 +
13 +use Automattic\Jetpack\Connection\Client;
14 +use Automattic\Jetpack\Redirect;
15 +use Automattic\Jetpack\Status\Host;
16 +use Automattic\Jetpack\Status\Request;
17 +use Automattic\Jetpack\Sync\Functions;
18 +
19 +// Disable direct access.
20 +if ( ! defined( 'ABSPATH' ) ) {
21 + exit( 0 );
22 +}
23 +
24 +require_once __DIR__ . '/functions.is-mobile.php';
25 +
26 +/**
27 + * Hook into Core's _deprecated_function
28 + * Add more details about when a deprecated function will be removed.
29 + *
30 + * @since 8.8.0
31 + *
32 + * @param string $function The function that was called.
33 + * @param string $replacement Optional. The function that should have been called. Default null.
34 + * @param string $version The version of Jetpack that deprecated the function.
35 + */
36 +function jetpack_deprecated_function( $function, $replacement, $version ) {
37 + // Bail early for non-Jetpack deprecations.
38 + if ( ! str_starts_with( $version, 'jetpack-' ) ) {
39 + return;
40 + }
41 +
42 + // Look for when a function will be removed based on when it was deprecated.
43 + $removed_version = jetpack_get_future_removed_version( $version );
44 +
45 + // If we could find a version, let's log a message about when removal will happen.
46 + if (
47 + ! empty( $removed_version )
48 + && ( defined( 'WP_DEBUG' ) && WP_DEBUG )
49 + /** This filter is documented in core/src/wp-includes/functions.php */
50 + && apply_filters( 'deprecated_function_trigger_error', true )
51 + ) {
52 + error_log( // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
53 + sprintf(
54 + doing_action( 'after_setup_theme' ) || did_action( 'after_setup_theme' ) ?
55 + /* Translators: 1. Function name. 2. Jetpack version number. */
56 + __( 'The %1$s function will be removed from the Jetpack plugin in version %2$s.', 'jetpack' )
57 + : 'The %1$s function will be removed from the Jetpack plugin in version %2$s.',
58 + $function,
59 + $removed_version
60 + )
61 + );
62 +
63 + }
64 +}
65 +add_action( 'deprecated_function_run', 'jetpack_deprecated_function', 10, 3 );
66 +
67 +/**
68 + * Hook into Core's _deprecated_file
69 + * Add more details about when a deprecated file will be removed.
70 + *
71 + * @since 8.8.0
72 + *
73 + * @param string $file The file that was called.
74 + * @param string $replacement The file that should have been included based on ABSPATH.
75 + * @param string $version The version of WordPress that deprecated the file.
76 + * @param string $message A message regarding the change.
77 + */
78 +function jetpack_deprecated_file( $file, $replacement, $version, $message ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
79 + // Bail early for non-Jetpack deprecations.
80 + if ( ! str_starts_with( $version, 'jetpack-' ) ) {
81 + return;
82 + }
83 +
84 + // Look for when a file will be removed based on when it was deprecated.
85 + $removed_version = jetpack_get_future_removed_version( $version );
86 +
87 + // If we could find a version, let's log a message about when removal will happen.
88 + if (
89 + ! empty( $removed_version )
90 + && ( defined( 'WP_DEBUG' ) && WP_DEBUG )
91 + /** This filter is documented in core/src/wp-includes/functions.php */
92 + && apply_filters( 'deprecated_file_trigger_error', true )
93 + ) {
94 + error_log( // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
95 + sprintf(
96 + /* Translators: 1. File name. 2. Jetpack version number. */
97 + __( 'The %1$s file will be removed from the Jetpack plugin in version %2$s.', 'jetpack' ),
98 + $file,
99 + $removed_version
100 + )
101 + );
102 +
103 + }
104 +}
105 +add_action( 'deprecated_file_included', 'jetpack_deprecated_file', 10, 4 );
106 +
107 +/**
108 + * Get the major version number of Jetpack 6 months after provided version.
109 + * Useful to indicate when a deprecated function will be removed from Jetpack.
110 + *
111 + * @since 8.8.0
112 + *
113 + * @param string $version The version of WordPress that deprecated the function.
114 + *
115 + * @return bool|float Return a Jetpack Major version number, or false.
116 + */
117 +function jetpack_get_future_removed_version( $version ) {
118 + /*
119 + * Extract the version number from a deprecation notice.
120 + * (let's only keep the first decimal, e.g. 8.8 and not 8.8.0)
121 + */
122 + preg_match( '#(([0-9]+\.([0-9]+))(?:\.[0-9]+)*)#', $version, $matches );
123 +
124 + if ( isset( $matches[2] ) && isset( $matches[3] ) ) {
125 + $deprecated_version = (float) $matches[2];
126 + $deprecated_minor = (float) $matches[3];
127 +
128 + /*
129 + * If the detected minor version number
130 + * (e.g. "7" in "8.7")
131 + * is higher than 9, we know the version number is malformed.
132 + * Jetpack does not use semver yet.
133 + * Bail.
134 + */
135 + if ( 10 <= $deprecated_minor ) {
136 + return false;
137 + }
138 +
139 + // We'll remove the function from the code 6 months later, thus 6 major versions later.
140 + $removed_version = $deprecated_version + 0.6;
141 +
142 + return $removed_version;
143 + }
144 +
145 + return false;
146 +}
147 +
148 +/**
149 + * Determine if this site is an WoA site or not by looking for presence of the wpcomsh plugin.
150 + *
151 + * @since 4.8.1
152 + * @deprecated 10.3.0
153 + *
154 + * @return bool
155 + */
156 +function jetpack_is_atomic_site() {
157 + jetpack_deprecated_function( __FUNCTION__, 'Automattic/Jetpack/Status/Host::is_woa_site', 'jetpack-10.3.0' );
158 + return ( new Host() )->is_woa_site();
159 +}
160 +
161 +/**
162 + * Register post type for migration.
163 + *
164 + * @since 5.2
165 + */
166 +function jetpack_register_migration_post_type() {
167 + register_post_type(
168 + 'jetpack_migration',
169 + array(
170 + 'supports' => array(),
171 + 'taxonomies' => array(),
172 + 'hierarchical' => false,
173 + 'public' => false,
174 + 'has_archive' => false,
175 + 'can_export' => true,
176 + )
177 + );
178 +}
179 +
180 +/**
181 + * Checks whether the Post DB threat currently exists on the site.
182 + *
183 + * @since 12.0
184 + *
185 + * @param string $option_name Option name.
186 + *
187 + * @return WP_Post|bool
188 + */
189 +function jetpack_migration_post_exists( $option_name ) {
190 + $query = new WP_Query(
191 + array(
192 + 'post_type' => 'jetpack_migration',
193 + 'title' => $option_name,
194 + 'post_status' => 'all',
195 + 'posts_per_page' => 1,
196 + 'no_found_rows' => true,
197 + 'ignore_sticky_posts' => true,
198 + 'update_post_term_cache' => false,
199 + 'update_post_meta_cache' => false,
200 + 'orderby' => 'post_date ID',
201 + 'order' => 'ASC',
202 + )
203 + );
204 + if ( ! empty( $query->post ) ) {
205 + return $query->post;
206 + }
207 +
208 + return false;
209 +}
210 +
211 +/**
212 + * Stores migration data in the database.
213 + *
214 + * @since 5.2
215 + *
216 + * @param string $option_name Option name.
217 + * @param bool $option_value Option value.
218 + *
219 + * @return int|WP_Error
220 + */
221 +function jetpack_store_migration_data( $option_name, $option_value ) {
222 + jetpack_register_migration_post_type();
223 +
224 + $insert = array(
225 + 'post_title' => $option_name,
226 + 'post_content_filtered' => $option_value,
227 + 'post_type' => 'jetpack_migration',
228 + 'post_date' => gmdate( 'Y-m-d H:i:s', time() ),
229 + );
230 +
231 + $migration_post = jetpack_migration_post_exists( $option_name );
232 + if ( $migration_post ) {
233 + $insert['ID'] = $migration_post->ID;
234 + }
235 +
236 + return wp_insert_post( $insert, true );
237 +}
238 +
239 +/**
240 + * Retrieves legacy image widget data.
241 + *
242 + * @since 5.2
243 + *
244 + * @param string $option_name Option name.
245 + *
246 + * @return mixed|null
247 + */
248 +function jetpack_get_migration_data( $option_name ) {
249 + $post = jetpack_migration_post_exists( $option_name );
250 +
251 + return null !== $post ? maybe_unserialize( $post->post_content_filtered ) : null;
252 +}
253 +
254 +/**
255 + * Prints a TOS blurb used throughout the connection prompts.
256 + *
257 + * @since 5.3
258 + *
259 + * @echo string
260 + */
261 +function jetpack_render_tos_blurb() {
262 + printf(
263 + wp_kses(
264 + /* Translators: placeholders are links. */
265 + __( 'By clicking <strong>Set up Jetpack</strong>, you agree to our <a href="%1$s" target="_blank" rel="noopener noreferrer">Terms of Service</a> and to <a href="%2$s" target="_blank" rel="noopener noreferrer">sync your site‘s data</a> with us.', 'jetpack' ),
266 + array(
267 + 'a' => array(
268 + 'href' => array(),
269 + 'target' => array(),
270 + 'rel' => array(),
271 + ),
272 + 'strong' => true,
273 + )
274 + ),
275 + esc_url( Redirect::get_url( 'wpcom-tos' ) ),
276 + esc_url( Redirect::get_url( 'jetpack-support-what-data-does-jetpack-sync' ) )
277 + );
278 +}
279 +
280 +/**
281 + * Intervene upgrade process so Jetpack themes are downloaded with credentials.
282 + *
283 + * @since 5.3
284 + *
285 + * @param bool $preempt Whether to preempt an HTTP request's return value. Default false.
286 + * @param array $r HTTP request arguments.
287 + * @param string $url The request URL.
288 + *
289 + * @return array|bool|WP_Error
290 + */
291 +function jetpack_theme_update( $preempt, $r, $url ) {
292 + if ( 0 === stripos( $url, JETPACK__WPCOM_JSON_API_BASE . '/rest/v1/themes/download' ) ) {
293 + $file = $r['filename'];
294 + if ( ! $file ) {
295 + return new WP_Error( 'problem_creating_theme_file', esc_html__( 'Problem creating file for theme download', 'jetpack' ) );
296 + }
297 + $theme = pathinfo( wp_parse_url( $url, PHP_URL_PATH ), PATHINFO_FILENAME );
298 +
299 + // Remove filter to avoid endless loop since wpcom_json_api_request_as_blog uses this too.
300 + remove_filter( 'pre_http_request', 'jetpack_theme_update' );
301 + $result = Client::wpcom_json_api_request_as_blog(
302 + "themes/download/$theme.zip",
303 + '1.1',
304 + array(
305 + 'stream' => true,
306 + 'filename' => $file,
307 + )
308 + );
309 +
310 + if ( 200 !== wp_remote_retrieve_response_code( $result ) ) {
311 + return new WP_Error( 'problem_fetching_theme', esc_html__( 'Problem downloading theme', 'jetpack' ) );
312 + }
313 + return $result;
314 + }
315 + return $preempt;
316 +}
317 +
318 +/**
319 + * Add the filter when a upgrade is going to be downloaded.
320 + *
321 + * @since 5.3
322 + *
323 + * @param bool $reply Whether to bail without returning the package. Default false.
324 + *
325 + * @return bool
326 + */
327 +function jetpack_upgrader_pre_download( $reply ) {
328 + add_filter( 'pre_http_request', 'jetpack_theme_update', 10, 3 );
329 + return $reply;
330 +}
331 +
332 +add_filter( 'upgrader_pre_download', 'jetpack_upgrader_pre_download' );
333 +
334 +/**
335 + * Wraps data in a way so that we can distinguish between objects and array and also prevent object recursion.
336 + *
337 + * @since 6.1.0
338 +
339 + * @deprecated Automattic\Jetpack\Sync\Functions::json_wrap
340 + *
341 + * @param mixed $any Source data to be cleaned up.
342 + * @param array $seen_nodes Built array of nodes.
343 + *
344 + * @return array
345 + */
346 +function jetpack_json_wrap( &$any, $seen_nodes = array() ) {
347 + _deprecated_function( __METHOD__, 'jetpack-9.5', 'Automattic\Jetpack\Sync\Functions' );
348 +
349 + return Functions::json_wrap( $any, $seen_nodes );
350 +}
351 +
352 +/**
353 + * Checks if the mime_content_type function is available and return it if so.
354 + *
355 + * The function mime_content_type is enabled by default in PHP, but can be disabled. We attempt to
356 + * enforce this via composer.json, but that won't be checked in majority of cases where
357 + * this would be happening.
358 + *
359 + * @since 7.8.0
360 + *
361 + * @param string $file File location.
362 + *
363 + * @return string|false MIME type or false if functionality is not available.
364 + */
365 +function jetpack_mime_content_type( $file ) {
366 + if ( function_exists( 'mime_content_type' ) ) {
367 + return mime_content_type( $file );
368 + }
369 +
370 + return false;
371 +}
372 +
373 +/**
374 + * Checks that the mime type of the specified file is among those in a filterable list of mime types.
375 + *
376 + * @since 7.8.0
377 + *
378 + * @param string $file Path to file to get its mime type.
379 + *
380 + * @return bool
381 + */
382 +function jetpack_is_file_supported_for_sideloading( $file ) {
383 + $type = jetpack_mime_content_type( $file );
384 +
385 + if ( ! $type ) {
386 + return false;
387 + }
388 +
389 + /**
390 + * Filter the list of supported mime types for media sideloading.
391 + *
392 + * @since 4.0.0
393 + *
394 + * @module json-api
395 + *
396 + * @param array $supported_mime_types Array of the supported mime types for media sideloading.
397 + */
398 + $supported_mime_types = apply_filters(
399 + 'jetpack_supported_media_sideload_types',
400 + array(
401 + 'image/png',
402 + 'image/jpeg',
403 + 'image/gif',
404 + 'image/bmp',
405 + 'image/webp',
406 + 'video/quicktime',
407 + 'video/mp4',
408 + 'video/mpeg',
409 + 'video/ogg',
410 + 'video/3gpp',
411 + 'video/3gpp2',
412 + 'video/h261',
413 + 'video/h262',
414 + 'video/h264',
415 + 'video/x-msvideo',
416 + 'video/x-ms-wmv',
417 + 'video/x-ms-asf',
418 + )
419 + );
420 +
421 + // If the type returned was not an array as expected, then we know we don't have a match.
422 + if ( ! is_array( $supported_mime_types ) ) {
423 + return false;
424 + }
425 +
426 + return in_array( $type, $supported_mime_types, true );
427 +}
428 +
429 +/**
430 + * Go through headers and get a list of Vary headers to add,
431 + * including a Vary Accept header if necessary.
432 + *
433 + * @since 12.2
434 + * @deprecated 14.8
435 + *
436 + * @param array $headers The headers to be sent.
437 + *
438 + * @return array $vary_header_parts Vary Headers to be sent.
439 + */
440 +function jetpack_get_vary_headers( $headers = array() ) {
441 + _deprecated_function( __FUNCTION__, '14.8', 'Automattic\Jetpack\Status\Request::get_vary_headers' );
442 +
443 + return ( new Request() )->get_vary_headers( $headers );
444 +}
445 +
446 +/**
447 + * Determine whether the current request is for accessing the frontend.
448 + * Also update Vary headers to indicate that the response may vary by Accept header.
449 + *
450 + * @deprecated 14.8
451 + *
452 + * @return bool True if it's a frontend request, false otherwise.
453 + */
454 +function jetpack_is_frontend() {
455 + _deprecated_function( __FUNCTION__, '14.8', 'Automattic\Jetpack\Status\Request::is_frontend' );
456 +
457 + return Request::is_frontend();
458 +}
459 +
460 +if ( ! function_exists( 'jetpack_mastodon_get_instance_list' ) ) {
461 + /**
462 + * Build a list of Mastodon instance hosts.
463 + * That list can be extended via a filter.
464 + *
465 + * @todo This function is now replicated in the Classic Theme Helper package and can be
466 + * removed here once Social Links are moved out of Jetpack.
467 + *
468 + * @since 11.8
469 + *
470 + * @return array
471 + */
472 + function jetpack_mastodon_get_instance_list() {
473 + $mastodon_instance_list = array(
474 + // Regex pattern to match any .tld for the mastodon host name.
475 + '#https?:\/\/(www\.)?mastodon\.(\w+)(\.\w+)?#',
476 + // Regex pattern to match any .tld for the mstdn host name.
477 + '#https?:\/\/(www\.)?mstdn\.(\w+)(\.\w+)?#',
478 + 'counter.social',
479 + 'fosstodon.org',
480 + 'gc2.jp',
481 + 'hachyderm.io',
482 + 'infosec.exchange',
483 + 'mas.to',
484 + 'pawoo.net',
485 + );
486 +
487 + /**
488 + * Filter the list of Mastodon instances.
489 + *
490 + * @since 11.8
491 + *
492 + * @module widgets, theme-tools
493 + *
494 + * @param array $mastodon_instance_list Array of Mastodon instances.
495 + */
496 + return (array) apply_filters( 'jetpack_mastodon_instance_list', $mastodon_instance_list );
497 + }
498 +}
499 +
500 +if ( ! function_exists( 'jetpack_is_internal_testing_environment' ) ) {
501 + /**
502 + * Check if the site is an A8C-internal testing environment.
503 + *
504 + * Returns true for localhost, Jurassic Ninja/Tube sandboxes, A8C proxied
505 + * requests, and known Atomic client IDs used for internal testing. Useful
506 + * for tagging analytics events as test traffic so they can be filtered out
507 + * of production reporting.
508 + *
509 + * Not to be confused with Jetpack's legacy "Development Mode", which is now
510 + * Status::is_offline_mode() and controls whether Jetpack connects to
511 + * WordPress.com.
512 + *
513 + * Note: This intentionally duplicates the logic from
514 + * Agents_Manager::is_dev_mode() in jetpack-agents-manager rather than calling
515 + * it directly, because that package is only available on WordPress.com
516 + * hosted sites, while Jetpack also runs on self-hosted sites.
517 + *
518 + * @since 15.8
519 + *
520 + * @return bool
521 + */
522 + function jetpack_is_internal_testing_environment() {
523 + // Known local environments.
524 + $domain = (string) wp_parse_url( get_site_url(), PHP_URL_HOST );
525 + if (
526 + $domain === 'localhost' ||
527 + '.jurassic.tube' === stristr( $domain, '.jurassic.tube' ) ||
528 + '.jurassic.ninja' === stristr( $domain, '.jurassic.ninja' )
529 + ) {
530 + return true;
531 + }
532 +
533 + // Proxied A8C request via function.
534 + if ( function_exists( 'wpcom_is_proxied_request' ) && wpcom_is_proxied_request() ) {
535 + return true;
536 + }
537 +
538 + // Proxied A8C request via server variable or constant.
539 + if (
540 + ( isset( $_SERVER['A8C_PROXIED_REQUEST'] ) && (bool) sanitize_text_field( wp_unslash( $_SERVER['A8C_PROXIED_REQUEST'] ) ) ) ||
541 + ( defined( 'A8C_PROXIED_REQUEST' ) && A8C_PROXIED_REQUEST )
542 + ) {
543 + return true;
544 + }
545 +
546 + if ( defined( 'AT_PROXIED_REQUEST' ) && AT_PROXIED_REQUEST && defined( 'ATOMIC_CLIENT_ID' ) ) {
547 + switch ( ATOMIC_CLIENT_ID ) {
548 + case 1:
549 + case 2:
550 + case 3:
551 + case 32:
552 + case 118:
553 + return true;
554 + }
555 + }
556 +
557 + return false;
558 + }
559 +}