Issues (2010)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

wp-includes/update.php (10 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * A simple set of functions to check our version 1.0 update service.
4
 *
5
 * @package WordPress
6
 * @since 2.3.0
7
 */
8
9
/**
10
 * Check WordPress version against the newest version.
11
 *
12
 * The WordPress version, PHP version, and Locale is sent. Checks against the
13
 * WordPress server at api.wordpress.org server. Will only check if WordPress
14
 * isn't installing.
15
 *
16
 * @since 2.3.0
17
 * @global string $wp_version Used to check against the newest WordPress version.
18
 * @global wpdb   $wpdb
19
 * @global string $wp_local_package
20
 *
21
 * @param array $extra_stats Extra statistics to report to the WordPress.org API.
22
 * @param bool  $force_check Whether to bypass the transient cache and force a fresh update check. Defaults to false, true if $extra_stats is set.
23
 */
24
function wp_version_check( $extra_stats = array(), $force_check = false ) {
25
	if ( wp_installing() ) {
26
		return;
27
	}
28
29
	global $wpdb, $wp_local_package;
30
	// include an unmodified $wp_version
31
	include( ABSPATH . WPINC . '/version.php' );
32
	$php_version = phpversion();
33
34
	$current = get_site_transient( 'update_core' );
35
	$translations = wp_get_installed_translations( 'core' );
36
37
	// Invalidate the transient when $wp_version changes
38
	if ( is_object( $current ) && $wp_version != $current->version_checked )
0 ignored issues
show
The variable $wp_version does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
39
		$current = false;
40
41
	if ( ! is_object($current) ) {
42
		$current = new stdClass;
43
		$current->updates = array();
44
		$current->version_checked = $wp_version;
45
	}
46
47
	if ( ! empty( $extra_stats ) )
48
		$force_check = true;
49
50
	// Wait 60 seconds between multiple version check requests
51
	$timeout = 60;
52
	$time_not_changed = isset( $current->last_checked ) && $timeout > ( time() - $current->last_checked );
53
	if ( ! $force_check && $time_not_changed ) {
54
		return;
55
	}
56
57
	/**
58
	 * Filters the locale requested for WordPress core translations.
59
	 *
60
	 * @since 2.8.0
61
	 *
62
	 * @param string $locale Current locale.
63
	 */
64
	$locale = apply_filters( 'core_version_check_locale', get_locale() );
65
66
	// Update last_checked for current to prevent multiple blocking requests if request hangs
67
	$current->last_checked = time();
68
	set_site_transient( 'update_core', $current );
69
70
	if ( method_exists( $wpdb, 'db_version' ) )
71
		$mysql_version = preg_replace('/[^0-9.].*/', '', $wpdb->db_version());
72
	else
73
		$mysql_version = 'N/A';
74
75
	if ( is_multisite() ) {
76
		$user_count = get_user_count();
77
		$num_blogs = get_blog_count();
78
		$wp_install = network_site_url();
79
		$multisite_enabled = 1;
80
	} else {
81
		$user_count = count_users();
82
		$user_count = $user_count['total_users'];
83
		$multisite_enabled = 0;
84
		$num_blogs = 1;
85
		$wp_install = home_url( '/' );
86
	}
87
88
	$query = array(
89
		'version'            => $wp_version,
90
		'php'                => $php_version,
91
		'locale'             => $locale,
92
		'mysql'              => $mysql_version,
93
		'local_package'      => isset( $wp_local_package ) ? $wp_local_package : '',
94
		'blogs'              => $num_blogs,
95
		'users'              => $user_count,
96
		'multisite_enabled'  => $multisite_enabled,
97
		'initial_db_version' => get_site_option( 'initial_db_version' ),
98
	);
99
100
	$post_body = array(
101
		'translations' => wp_json_encode( $translations ),
102
	);
103
104
	if ( is_array( $extra_stats ) )
105
		$post_body = array_merge( $post_body, $extra_stats );
106
107
	$url = $http_url = 'http://api.wordpress.org/core/version-check/1.7/?' . http_build_query( $query, null, '&' );
108
	if ( $ssl = wp_http_supports( array( 'ssl' ) ) )
109
		$url = set_url_scheme( $url, 'https' );
110
111
	$options = array(
112
		'timeout' => ( ( defined('DOING_CRON') && DOING_CRON ) ? 30 : 3 ),
113
		'user-agent' => 'WordPress/' . $wp_version . '; ' . home_url( '/' ),
114
		'headers' => array(
115
			'wp_install' => $wp_install,
116
			'wp_blog' => home_url( '/' )
117
		),
118
		'body' => $post_body,
119
	);
120
121
	$response = wp_remote_post( $url, $options );
122 View Code Duplication
	if ( $ssl && is_wp_error( $response ) ) {
123
		trigger_error( __( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="https://wordpress.org/support/">support forums</a>.' ) . ' ' . __( '(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)' ), headers_sent() || WP_DEBUG ? E_USER_WARNING : E_USER_NOTICE );
124
		$response = wp_remote_post( $http_url, $options );
125
	}
126
127
	if ( is_wp_error( $response ) || 200 != wp_remote_retrieve_response_code( $response ) ) {
0 ignored issues
show
It seems like $response can also be of type object<WP_Error>; however, wp_remote_retrieve_response_code() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
128
		return;
129
	}
130
131
	$body = trim( wp_remote_retrieve_body( $response ) );
0 ignored issues
show
It seems like $response can also be of type object<WP_Error>; however, wp_remote_retrieve_body() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
132
	$body = json_decode( $body, true );
133
134
	if ( ! is_array( $body ) || ! isset( $body['offers'] ) ) {
135
		return;
136
	}
137
138
	$offers = $body['offers'];
139
140
	foreach ( $offers as &$offer ) {
141
		foreach ( $offer as $offer_key => $value ) {
142
			if ( 'packages' == $offer_key )
143
				$offer['packages'] = (object) array_intersect_key( array_map( 'esc_url', $offer['packages'] ),
144
					array_fill_keys( array( 'full', 'no_content', 'new_bundled', 'partial', 'rollback' ), '' ) );
145
			elseif ( 'download' == $offer_key )
146
				$offer['download'] = esc_url( $value );
147
			else
148
				$offer[ $offer_key ] = esc_html( $value );
149
		}
150
		$offer = (object) array_intersect_key( $offer, array_fill_keys( array( 'response', 'download', 'locale',
151
			'packages', 'current', 'version', 'php_version', 'mysql_version', 'new_bundled', 'partial_version', 'notify_email', 'support_email', 'new_files' ), '' ) );
152
	}
153
154
	$updates = new stdClass();
155
	$updates->updates = $offers;
156
	$updates->last_checked = time();
157
	$updates->version_checked = $wp_version;
158
159
	if ( isset( $body['translations'] ) )
160
		$updates->translations = $body['translations'];
161
162
	set_site_transient( 'update_core', $updates );
163
164
	if ( ! empty( $body['ttl'] ) ) {
165
		$ttl = (int) $body['ttl'];
166
		if ( $ttl && ( time() + $ttl < wp_next_scheduled( 'wp_version_check' ) ) ) {
167
			// Queue an event to re-run the update check in $ttl seconds.
168
			wp_schedule_single_event( time() + $ttl, 'wp_version_check' );
169
		}
170
	}
171
172
	// Trigger background updates if running non-interactively, and we weren't called from the update handler.
173
	if ( defined( 'DOING_CRON' ) && DOING_CRON && ! doing_action( 'wp_maybe_auto_update' ) ) {
174
		do_action( 'wp_maybe_auto_update' );
175
	}
176
}
177
178
/**
179
 * Check plugin versions against the latest versions hosted on WordPress.org.
180
 *
181
 * The WordPress version, PHP version, and Locale is sent along with a list of
182
 * all plugins installed. Checks against the WordPress server at
183
 * api.wordpress.org. Will only check if WordPress isn't installing.
184
 *
185
 * @since 2.3.0
186
 * @global string $wp_version Used to notify the WordPress version.
187
 *
188
 * @param array $extra_stats Extra statistics to report to the WordPress.org API.
189
 */
190
function wp_update_plugins( $extra_stats = array() ) {
191
	if ( wp_installing() ) {
192
		return;
193
	}
194
195
	// include an unmodified $wp_version
196
	include( ABSPATH . WPINC . '/version.php' );
197
198
	// If running blog-side, bail unless we've not checked in the last 12 hours
199
	if ( !function_exists( 'get_plugins' ) )
200
		require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
201
202
	$plugins = get_plugins();
203
	$translations = wp_get_installed_translations( 'plugins' );
204
205
	$active  = get_option( 'active_plugins', array() );
206
	$current = get_site_transient( 'update_plugins' );
207
	if ( ! is_object($current) )
208
		$current = new stdClass;
209
210
	$new_option = new stdClass;
211
	$new_option->last_checked = time();
212
213
	// Check for update on a different schedule, depending on the page.
214 View Code Duplication
	switch ( current_filter() ) {
215
		case 'upgrader_process_complete' :
216
			$timeout = 0;
217
			break;
218
		case 'load-update-core.php' :
219
			$timeout = MINUTE_IN_SECONDS;
220
			break;
221
		case 'load-plugins.php' :
222
		case 'load-update.php' :
223
			$timeout = HOUR_IN_SECONDS;
224
			break;
225
		default :
226
			if ( defined( 'DOING_CRON' ) && DOING_CRON ) {
227
				$timeout = 0;
228
			} else {
229
				$timeout = 12 * HOUR_IN_SECONDS;
230
			}
231
	}
232
233
	$time_not_changed = isset( $current->last_checked ) && $timeout > ( time() - $current->last_checked );
234
235
	if ( $time_not_changed && ! $extra_stats ) {
236
		$plugin_changed = false;
237
		foreach ( $plugins as $file => $p ) {
238
			$new_option->checked[ $file ] = $p['Version'];
239
240
			if ( !isset( $current->checked[ $file ] ) || strval($current->checked[ $file ]) !== strval($p['Version']) )
241
				$plugin_changed = true;
242
		}
243
244
		if ( isset ( $current->response ) && is_array( $current->response ) ) {
245
			foreach ( $current->response as $plugin_file => $update_details ) {
246
				if ( ! isset($plugins[ $plugin_file ]) ) {
247
					$plugin_changed = true;
248
					break;
249
				}
250
			}
251
		}
252
253
		// Bail if we've checked recently and if nothing has changed
254
		if ( ! $plugin_changed ) {
255
			return;
256
		}
257
	}
258
259
	// Update last_checked for current to prevent multiple blocking requests if request hangs
260
	$current->last_checked = time();
261
	set_site_transient( 'update_plugins', $current );
262
263
	$to_send = compact( 'plugins', 'active' );
264
265
	$locales = array_values( get_available_languages() );
266
267
	/**
268
	 * Filters the locales requested for plugin translations.
269
	 *
270
	 * @since 3.7.0
271
	 * @since 4.5.0 The default value of the `$locales` parameter changed to include all locales.
272
	 *
273
	 * @param array $locales Plugin locales. Default is all available locales of the site.
274
	 */
275
	$locales = apply_filters( 'plugins_update_check_locales', $locales );
276
	$locales = array_unique( $locales );
277
278 View Code Duplication
	if ( defined( 'DOING_CRON' ) && DOING_CRON ) {
279
		$timeout = 30;
280
	} else {
281
		// Three seconds, plus one extra second for every 10 plugins
282
		$timeout = 3 + (int) ( count( $plugins ) / 10 );
283
	}
284
285
	$options = array(
286
		'timeout' => $timeout,
287
		'body' => array(
288
			'plugins'      => wp_json_encode( $to_send ),
289
			'translations' => wp_json_encode( $translations ),
290
			'locale'       => wp_json_encode( $locales ),
291
			'all'          => wp_json_encode( true ),
292
		),
293
		'user-agent' => 'WordPress/' . $wp_version . '; ' . get_bloginfo( 'url' )
0 ignored issues
show
The variable $wp_version does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
294
	);
295
296
	if ( $extra_stats ) {
297
		$options['body']['update_stats'] = wp_json_encode( $extra_stats );
298
	}
299
300
	$url = $http_url = 'http://api.wordpress.org/plugins/update-check/1.1/';
301
	if ( $ssl = wp_http_supports( array( 'ssl' ) ) )
302
		$url = set_url_scheme( $url, 'https' );
303
304
	$raw_response = wp_remote_post( $url, $options );
305 View Code Duplication
	if ( $ssl && is_wp_error( $raw_response ) ) {
306
		trigger_error( __( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="https://wordpress.org/support/">support forums</a>.' ) . ' ' . __( '(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)' ), headers_sent() || WP_DEBUG ? E_USER_WARNING : E_USER_NOTICE );
307
		$raw_response = wp_remote_post( $http_url, $options );
308
	}
309
310
	if ( is_wp_error( $raw_response ) || 200 != wp_remote_retrieve_response_code( $raw_response ) ) {
0 ignored issues
show
It seems like $raw_response can also be of type object<WP_Error>; however, wp_remote_retrieve_response_code() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
311
		return;
312
	}
313
314
	$response = json_decode( wp_remote_retrieve_body( $raw_response ), true );
0 ignored issues
show
It seems like $raw_response can also be of type object<WP_Error>; however, wp_remote_retrieve_body() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
315
	foreach ( $response['plugins'] as &$plugin ) {
316
		$plugin = (object) $plugin;
317
		if ( isset( $plugin->compatibility ) ) {
318
			$plugin->compatibility = (object) $plugin->compatibility;
319
			foreach ( $plugin->compatibility as &$data ) {
320
				$data = (object) $data;
321
			}
322
		}
323
	}
324
	unset( $plugin, $data );
325
	foreach ( $response['no_update'] as &$plugin ) {
326
		$plugin = (object) $plugin;
327
	}
328
	unset( $plugin );
329
330
	if ( is_array( $response ) ) {
331
		$new_option->response = $response['plugins'];
332
		$new_option->translations = $response['translations'];
333
		// TODO: Perhaps better to store no_update in a separate transient with an expiry?
334
		$new_option->no_update = $response['no_update'];
335
	} else {
336
		$new_option->response = array();
337
		$new_option->translations = array();
338
		$new_option->no_update = array();
339
	}
340
341
	set_site_transient( 'update_plugins', $new_option );
342
}
343
344
/**
345
 * Check theme versions against the latest versions hosted on WordPress.org.
346
 *
347
 * A list of all themes installed in sent to WP. Checks against the
348
 * WordPress server at api.wordpress.org. Will only check if WordPress isn't
349
 * installing.
350
 *
351
 * @since 2.7.0
352
 *
353
 * @param array $extra_stats Extra statistics to report to the WordPress.org API.
354
 */
355
function wp_update_themes( $extra_stats = array() ) {
356
	if ( wp_installing() ) {
357
		return;
358
	}
359
360
	// include an unmodified $wp_version
361
	include( ABSPATH . WPINC . '/version.php' );
362
363
	$installed_themes = wp_get_themes();
364
	$translations = wp_get_installed_translations( 'themes' );
365
366
	$last_update = get_site_transient( 'update_themes' );
367
	if ( ! is_object($last_update) )
368
		$last_update = new stdClass;
369
370
	$themes = $checked = $request = array();
371
372
	// Put slug of current theme into request.
373
	$request['active'] = get_option( 'stylesheet' );
374
375
	foreach ( $installed_themes as $theme ) {
376
		$checked[ $theme->get_stylesheet() ] = $theme->get('Version');
377
378
		$themes[ $theme->get_stylesheet() ] = array(
379
			'Name'       => $theme->get('Name'),
380
			'Title'      => $theme->get('Name'),
381
			'Version'    => $theme->get('Version'),
382
			'Author'     => $theme->get('Author'),
383
			'Author URI' => $theme->get('AuthorURI'),
384
			'Template'   => $theme->get_template(),
385
			'Stylesheet' => $theme->get_stylesheet(),
386
		);
387
	}
388
389
	// Check for update on a different schedule, depending on the page.
390 View Code Duplication
	switch ( current_filter() ) {
391
		case 'upgrader_process_complete' :
392
			$timeout = 0;
393
			break;
394
		case 'load-update-core.php' :
395
			$timeout = MINUTE_IN_SECONDS;
396
			break;
397
		case 'load-themes.php' :
398
		case 'load-update.php' :
399
			$timeout = HOUR_IN_SECONDS;
400
			break;
401
		default :
402
			if ( defined( 'DOING_CRON' ) && DOING_CRON ) {
403
				$timeout = 0;
404
			} else {
405
				$timeout = 12 * HOUR_IN_SECONDS;
406
			}
407
	}
408
409
	$time_not_changed = isset( $last_update->last_checked ) && $timeout > ( time() - $last_update->last_checked );
410
411
	if ( $time_not_changed && ! $extra_stats ) {
412
		$theme_changed = false;
413
		foreach ( $checked as $slug => $v ) {
414
			if ( !isset( $last_update->checked[ $slug ] ) || strval($last_update->checked[ $slug ]) !== strval($v) )
415
				$theme_changed = true;
416
		}
417
418
		if ( isset ( $last_update->response ) && is_array( $last_update->response ) ) {
419
			foreach ( $last_update->response as $slug => $update_details ) {
420
				if ( ! isset($checked[ $slug ]) ) {
421
					$theme_changed = true;
422
					break;
423
				}
424
			}
425
		}
426
427
		// Bail if we've checked recently and if nothing has changed
428
		if ( ! $theme_changed ) {
429
			return;
430
		}
431
	}
432
433
	// Update last_checked for current to prevent multiple blocking requests if request hangs
434
	$last_update->last_checked = time();
435
	set_site_transient( 'update_themes', $last_update );
436
437
	$request['themes'] = $themes;
438
439
	$locales = array_values( get_available_languages() );
440
441
	/**
442
	 * Filters the locales requested for theme translations.
443
	 *
444
	 * @since 3.7.0
445
	 * @since 4.5.0 The default value of the `$locales` parameter changed to include all locales.
446
	 *
447
	 * @param array $locales Theme locales. Default is all available locales of the site.
448
	 */
449
	$locales = apply_filters( 'themes_update_check_locales', $locales );
450
	$locales = array_unique( $locales );
451
452 View Code Duplication
	if ( defined( 'DOING_CRON' ) && DOING_CRON ) {
453
		$timeout = 30;
454
	} else {
455
		// Three seconds, plus one extra second for every 10 themes
456
		$timeout = 3 + (int) ( count( $themes ) / 10 );
457
	}
458
459
	$options = array(
460
		'timeout' => $timeout,
461
		'body' => array(
462
			'themes'       => wp_json_encode( $request ),
463
			'translations' => wp_json_encode( $translations ),
464
			'locale'       => wp_json_encode( $locales ),
465
		),
466
		'user-agent'	=> 'WordPress/' . $wp_version . '; ' . get_bloginfo( 'url' )
0 ignored issues
show
The variable $wp_version does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
467
	);
468
469
	if ( $extra_stats ) {
470
		$options['body']['update_stats'] = wp_json_encode( $extra_stats );
471
	}
472
473
	$url = $http_url = 'http://api.wordpress.org/themes/update-check/1.1/';
474
	if ( $ssl = wp_http_supports( array( 'ssl' ) ) )
475
		$url = set_url_scheme( $url, 'https' );
476
477
	$raw_response = wp_remote_post( $url, $options );
478 View Code Duplication
	if ( $ssl && is_wp_error( $raw_response ) ) {
479
		trigger_error( __( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="https://wordpress.org/support/">support forums</a>.' ) . ' ' . __( '(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)' ), headers_sent() || WP_DEBUG ? E_USER_WARNING : E_USER_NOTICE );
480
		$raw_response = wp_remote_post( $http_url, $options );
481
	}
482
483
	if ( is_wp_error( $raw_response ) || 200 != wp_remote_retrieve_response_code( $raw_response ) ) {
0 ignored issues
show
It seems like $raw_response can also be of type object<WP_Error>; however, wp_remote_retrieve_response_code() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
484
		return;
485
	}
486
487
	$new_update = new stdClass;
488
	$new_update->last_checked = time();
489
	$new_update->checked = $checked;
490
491
	$response = json_decode( wp_remote_retrieve_body( $raw_response ), true );
0 ignored issues
show
It seems like $raw_response can also be of type object<WP_Error>; however, wp_remote_retrieve_body() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
492
493
	if ( is_array( $response ) ) {
494
		$new_update->response     = $response['themes'];
495
		$new_update->translations = $response['translations'];
496
	}
497
498
	set_site_transient( 'update_themes', $new_update );
499
}
500
501
/**
502
 * Performs WordPress automatic background updates.
503
 *
504
 * @since 3.7.0
505
 */
506
function wp_maybe_auto_update() {
507
	include_once( ABSPATH . '/wp-admin/includes/admin.php' );
508
	include_once( ABSPATH . '/wp-admin/includes/class-wp-upgrader.php' );
509
510
	$upgrader = new WP_Automatic_Updater;
511
	$upgrader->run();
512
}
513
514
/**
515
 * Retrieves a list of all language updates available.
516
 *
517
 * @since 3.7.0
518
 *
519
 * @return array
520
 */
521
function wp_get_translation_updates() {
522
	$updates = array();
523
	$transients = array( 'update_core' => 'core', 'update_plugins' => 'plugin', 'update_themes' => 'theme' );
524
	foreach ( $transients as $transient => $type ) {
525
		$transient = get_site_transient( $transient );
526
		if ( empty( $transient->translations ) )
527
			continue;
528
529
		foreach ( $transient->translations as $translation ) {
530
			$updates[] = (object) $translation;
531
		}
532
	}
533
	return $updates;
534
}
535
536
/**
537
 * Collect counts and UI strings for available updates
538
 *
539
 * @since 3.3.0
540
 *
541
 * @return array
542
 */
543
function wp_get_update_data() {
544
	$counts = array( 'plugins' => 0, 'themes' => 0, 'wordpress' => 0, 'translations' => 0 );
545
546 View Code Duplication
	if ( $plugins = current_user_can( 'update_plugins' ) ) {
547
		$update_plugins = get_site_transient( 'update_plugins' );
548
		if ( ! empty( $update_plugins->response ) )
549
			$counts['plugins'] = count( $update_plugins->response );
550
	}
551
552 View Code Duplication
	if ( $themes = current_user_can( 'update_themes' ) ) {
553
		$update_themes = get_site_transient( 'update_themes' );
554
		if ( ! empty( $update_themes->response ) )
555
			$counts['themes'] = count( $update_themes->response );
556
	}
557
558
	if ( ( $core = current_user_can( 'update_core' ) ) && function_exists( 'get_core_updates' ) ) {
559
		$update_wordpress = get_core_updates( array('dismissed' => false) );
560
		if ( ! empty( $update_wordpress ) && ! in_array( $update_wordpress[0]->response, array('development', 'latest') ) && current_user_can('update_core') )
561
			$counts['wordpress'] = 1;
562
	}
563
564
	if ( ( $core || $plugins || $themes ) && wp_get_translation_updates() )
565
		$counts['translations'] = 1;
566
567
	$counts['total'] = $counts['plugins'] + $counts['themes'] + $counts['wordpress'] + $counts['translations'];
568
	$titles = array();
569
	if ( $counts['wordpress'] )
570
		$titles['wordpress'] = sprintf( __( '%d WordPress Update'), $counts['wordpress'] );
571
	if ( $counts['plugins'] )
572
		$titles['plugins'] = sprintf( _n( '%d Plugin Update', '%d Plugin Updates', $counts['plugins'] ), $counts['plugins'] );
573
	if ( $counts['themes'] )
574
		$titles['themes'] = sprintf( _n( '%d Theme Update', '%d Theme Updates', $counts['themes'] ), $counts['themes'] );
575
	if ( $counts['translations'] )
576
		$titles['translations'] = __( 'Translation Updates' );
577
578
	$update_title = $titles ? esc_attr( implode( ', ', $titles ) ) : '';
579
580
	$update_data = array( 'counts' => $counts, 'title' => $update_title );
581
	/**
582
	 * Filters the returned array of update data for plugins, themes, and WordPress core.
583
	 *
584
	 * @since 3.5.0
585
	 *
586
	 * @param array $update_data {
587
	 *     Fetched update data.
588
	 *
589
	 *     @type array   $counts       An array of counts for available plugin, theme, and WordPress updates.
590
	 *     @type string  $update_title Titles of available updates.
591
	 * }
592
	 * @param array $titles An array of update counts and UI strings for available updates.
593
	 */
594
	return apply_filters( 'wp_get_update_data', $update_data, $titles );
595
}
596
597
/**
598
 * Determines whether core should be updated.
599
 *
600
 * @since 2.8.0
601
 *
602
 * @global string $wp_version
603
 */
604
function _maybe_update_core() {
605
	// include an unmodified $wp_version
606
	include( ABSPATH . WPINC . '/version.php' );
607
608
	$current = get_site_transient( 'update_core' );
609
610
	if ( isset( $current->last_checked, $current->version_checked ) &&
611
		12 * HOUR_IN_SECONDS > ( time() - $current->last_checked ) &&
612
		$current->version_checked == $wp_version ) {
0 ignored issues
show
The variable $wp_version does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
613
		return;
614
	}
615
	wp_version_check();
616
}
617
/**
618
 * Check the last time plugins were run before checking plugin versions.
619
 *
620
 * This might have been backported to WordPress 2.6.1 for performance reasons.
621
 * This is used for the wp-admin to check only so often instead of every page
622
 * load.
623
 *
624
 * @since 2.7.0
625
 * @access private
626
 */
627
function _maybe_update_plugins() {
628
	$current = get_site_transient( 'update_plugins' );
629 View Code Duplication
	if ( isset( $current->last_checked ) && 12 * HOUR_IN_SECONDS > ( time() - $current->last_checked ) )
630
		return;
631
	wp_update_plugins();
632
}
633
634
/**
635
 * Check themes versions only after a duration of time.
636
 *
637
 * This is for performance reasons to make sure that on the theme version
638
 * checker is not run on every page load.
639
 *
640
 * @since 2.7.0
641
 * @access private
642
 */
643
function _maybe_update_themes() {
644
	$current = get_site_transient( 'update_themes' );
645 View Code Duplication
	if ( isset( $current->last_checked ) && 12 * HOUR_IN_SECONDS > ( time() - $current->last_checked ) )
646
		return;
647
	wp_update_themes();
648
}
649
650
/**
651
 * Schedule core, theme, and plugin update checks.
652
 *
653
 * @since 3.1.0
654
 */
655
function wp_schedule_update_checks() {
656
	if ( ! wp_next_scheduled( 'wp_version_check' ) && ! wp_installing() )
657
		wp_schedule_event(time(), 'twicedaily', 'wp_version_check');
658
659
	if ( ! wp_next_scheduled( 'wp_update_plugins' ) && ! wp_installing() )
660
		wp_schedule_event(time(), 'twicedaily', 'wp_update_plugins');
661
662
	if ( ! wp_next_scheduled( 'wp_update_themes' ) && ! wp_installing() )
663
		wp_schedule_event(time(), 'twicedaily', 'wp_update_themes');
664
}
665
666
/**
667
 * Clear existing update caches for plugins, themes, and core.
668
 *
669
 * @since 4.1.0
670
 */
671
function wp_clean_update_cache() {
672
	if ( function_exists( 'wp_clean_plugins_cache' ) ) {
673
		wp_clean_plugins_cache();
674
	} else {
675
		delete_site_transient( 'update_plugins' );
676
	}
677
	wp_clean_themes_cache();
678
	delete_site_transient( 'update_core' );
679
}
680
681
if ( ( ! is_main_site() && ! is_network_admin() ) || ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) {
682
	return;
683
}
684
685
add_action( 'admin_init', '_maybe_update_core' );
686
add_action( 'wp_version_check', 'wp_version_check' );
687
688
add_action( 'load-plugins.php', 'wp_update_plugins' );
689
add_action( 'load-update.php', 'wp_update_plugins' );
690
add_action( 'load-update-core.php', 'wp_update_plugins' );
691
add_action( 'admin_init', '_maybe_update_plugins' );
692
add_action( 'wp_update_plugins', 'wp_update_plugins' );
693
694
add_action( 'load-themes.php', 'wp_update_themes' );
695
add_action( 'load-update.php', 'wp_update_themes' );
696
add_action( 'load-update-core.php', 'wp_update_themes' );
697
add_action( 'admin_init', '_maybe_update_themes' );
698
add_action( 'wp_update_themes', 'wp_update_themes' );
699
700
add_action( 'update_option_WPLANG', 'wp_clean_update_cache' , 10, 0 );
701
702
add_action( 'wp_maybe_auto_update', 'wp_maybe_auto_update' );
703
704
add_action( 'init', 'wp_schedule_update_checks' );
705