Issues (4967)

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.

src/wp-admin/plugins.php (3 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
 * Plugins administration panel.
4
 *
5
 * @package WordPress
6
 * @subpackage Administration
7
 */
8
9
/** WordPress Administration Bootstrap */
10
require_once( dirname( __FILE__ ) . '/admin.php' );
11
12
if ( ! current_user_can('activate_plugins') )
13
	wp_die( __( 'Sorry, you are not allowed to manage plugins for this site.' ) );
14
15
$wp_list_table = _get_list_table('WP_Plugins_List_Table');
16
$pagenum = $wp_list_table->get_pagenum();
17
18
$action = $wp_list_table->current_action();
19
20
$plugin = isset($_REQUEST['plugin']) ? $_REQUEST['plugin'] : '';
21
$s = isset($_REQUEST['s']) ? urlencode( wp_unslash( $_REQUEST['s'] ) ) : '';
22
23
// Clean up request URI from temporary args for screen options/paging uri's to work as expected.
24
$_SERVER['REQUEST_URI'] = remove_query_arg(array('error', 'deleted', 'activate', 'activate-multi', 'deactivate', 'deactivate-multi', '_error_nonce'), $_SERVER['REQUEST_URI']);
25
26
wp_enqueue_script( 'updates' );
27
28
if ( $action ) {
29
30
	switch ( $action ) {
31
		case 'activate':
32
			if ( ! current_user_can('activate_plugins') )
33
				wp_die(__('Sorry, you are not allowed to activate plugins for this site.'));
34
35
			if ( is_multisite() && ! is_network_admin() && is_network_only_plugin( $plugin ) ) {
36
				wp_redirect( self_admin_url("plugins.php?plugin_status=$status&paged=$page&s=$s") );
37
				exit;
38
			}
39
40
			check_admin_referer('activate-plugin_' . $plugin);
41
42
			$result = activate_plugin($plugin, self_admin_url('plugins.php?error=true&plugin=' . $plugin), is_network_admin() );
43
			if ( is_wp_error( $result ) ) {
44
				if ( 'unexpected_output' == $result->get_error_code() ) {
45
					$redirect = self_admin_url('plugins.php?error=true&charsout=' . strlen($result->get_error_data()) . '&plugin=' . $plugin . "&plugin_status=$status&paged=$page&s=$s");
46
					wp_redirect(add_query_arg('_error_nonce', wp_create_nonce('plugin-activation-error_' . $plugin), $redirect));
47
					exit;
48
				} else {
49
					wp_die($result);
50
				}
51
			}
52
53
			if ( ! is_network_admin() ) {
54
				$recent = (array) get_option( 'recently_activated' );
55
				unset( $recent[ $plugin ] );
56
				update_option( 'recently_activated', $recent );
57
			} else {
58
				$recent = (array) get_site_option( 'recently_activated' );
59
				unset( $recent[ $plugin ] );
60
				update_site_option( 'recently_activated', $recent );
61
			}
62
63
			if ( isset($_GET['from']) && 'import' == $_GET['from'] ) {
64
				wp_redirect( self_admin_url("import.php?import=" . str_replace('-importer', '', dirname($plugin))) ); // overrides the ?error=true one above and redirects to the Imports page, stripping the -importer suffix
65
			} else {
66
				wp_redirect( self_admin_url("plugins.php?activate=true&plugin_status=$status&paged=$page&s=$s") ); // overrides the ?error=true one above
67
			}
68
			exit;
69
70
		case 'activate-selected':
71
			if ( ! current_user_can('activate_plugins') )
72
				wp_die(__('Sorry, you are not allowed to activate plugins for this site.'));
73
74
			check_admin_referer('bulk-plugins');
75
76
			$plugins = isset( $_POST['checked'] ) ? (array) $_POST['checked'] : array();
77
78
			if ( is_network_admin() ) {
79
				foreach ( $plugins as $i => $plugin ) {
80
					// Only activate plugins which are not already network activated.
81
					if ( is_plugin_active_for_network( $plugin ) ) {
82
						unset( $plugins[ $i ] );
83
					}
84
				}
85
			} else {
86
				foreach ( $plugins as $i => $plugin ) {
87
					// Only activate plugins which are not already active and are not network-only when on Multisite.
88
					if ( is_plugin_active( $plugin ) || ( is_multisite() && is_network_only_plugin( $plugin ) ) ) {
89
						unset( $plugins[ $i ] );
90
					}
91
				}
92
			}
93
94
			if ( empty($plugins) ) {
95
				wp_redirect( self_admin_url("plugins.php?plugin_status=$status&paged=$page&s=$s") );
96
				exit;
97
			}
98
99
			activate_plugins($plugins, self_admin_url('plugins.php?error=true'), is_network_admin() );
100
101
			if ( ! is_network_admin() ) {
102
				$recent = (array) get_option('recently_activated' );
103
			} else {
104
				$recent = (array) get_site_option('recently_activated' );
105
			}
106
107
			foreach ( $plugins as $plugin ) {
108
				unset( $recent[ $plugin ] );
109
			}
110
111
			if ( ! is_network_admin() ) {
112
				update_option( 'recently_activated', $recent );
113
			} else {
114
				update_site_option( 'recently_activated', $recent );
115
			}
116
117
			wp_redirect( self_admin_url("plugins.php?activate-multi=true&plugin_status=$status&paged=$page&s=$s") );
118
			exit;
119
120 View Code Duplication
		case 'update-selected' :
121
122
			check_admin_referer( 'bulk-plugins' );
123
124
			if ( isset( $_GET['plugins'] ) )
125
				$plugins = explode( ',', $_GET['plugins'] );
126
			elseif ( isset( $_POST['checked'] ) )
127
				$plugins = (array) $_POST['checked'];
128
			else
129
				$plugins = array();
130
131
			$title = __( 'Update Plugins' );
132
			$parent_file = 'plugins.php';
133
134
			wp_enqueue_script( 'updates' );
135
			require_once(ABSPATH . 'wp-admin/admin-header.php');
136
137
			echo '<div class="wrap">';
138
			echo '<h1>' . esc_html( $title ) . '</h1>';
139
140
			$url = self_admin_url('update.php?action=update-selected&amp;plugins=' . urlencode( join(',', $plugins) ));
141
			$url = wp_nonce_url($url, 'bulk-update-plugins');
142
143
			echo "<iframe src='$url' style='width: 100%; height:100%; min-height:850px;'></iframe>";
144
			echo '</div>';
145
			require_once(ABSPATH . 'wp-admin/admin-footer.php');
146
			exit;
147
148
		case 'error_scrape':
149
			if ( ! current_user_can('activate_plugins') )
150
				wp_die(__('Sorry, you are not allowed to activate plugins for this site.'));
151
152
			check_admin_referer('plugin-activation-error_' . $plugin);
153
154
			$valid = validate_plugin($plugin);
155
			if ( is_wp_error($valid) )
156
				wp_die($valid);
157
158 View Code Duplication
			if ( ! WP_DEBUG ) {
159
				error_reporting( E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_ERROR | E_WARNING | E_PARSE | E_USER_ERROR | E_USER_WARNING | E_RECOVERABLE_ERROR );
160
			}
161
162
			@ini_set('display_errors', true); //Ensure that Fatal errors are displayed.
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
163
			// Go back to "sandbox" scope so we get the same errors as before
164
			plugin_sandbox_scrape( $plugin );
165
			/** This action is documented in wp-admin/includes/plugin.php */
166
			do_action( "activate_{$plugin}" );
167
			exit;
168
169
		case 'deactivate':
170
			if ( ! current_user_can('activate_plugins') )
171
				wp_die(__('Sorry, you are not allowed to deactivate plugins for this site.'));
172
173
			check_admin_referer('deactivate-plugin_' . $plugin);
174
175
			if ( ! is_network_admin() && is_plugin_active_for_network( $plugin ) ) {
176
				wp_redirect( self_admin_url("plugins.php?plugin_status=$status&paged=$page&s=$s") );
177
				exit;
178
			}
179
180
			deactivate_plugins( $plugin, false, is_network_admin() );
181
182 View Code Duplication
			if ( ! is_network_admin() ) {
183
				update_option( 'recently_activated', array( $plugin => time() ) + (array) get_option( 'recently_activated' ) );
184
			} else {
185
				update_site_option( 'recently_activated', array( $plugin => time() ) + (array) get_site_option( 'recently_activated' ) );
186
			}
187
188
			if ( headers_sent() )
189
				echo "<meta http-equiv='refresh' content='" . esc_attr( "0;url=plugins.php?deactivate=true&plugin_status=$status&paged=$page&s=$s" ) . "' />";
190
			else
191
				wp_redirect( self_admin_url("plugins.php?deactivate=true&plugin_status=$status&paged=$page&s=$s") );
192
			exit;
193
194
		case 'deactivate-selected':
195
			if ( ! current_user_can('activate_plugins') )
196
				wp_die(__('Sorry, you are not allowed to deactivate plugins for this site.'));
197
198
			check_admin_referer('bulk-plugins');
199
200
			$plugins = isset( $_POST['checked'] ) ? (array) $_POST['checked'] : array();
201
			// Do not deactivate plugins which are already deactivated.
202
			if ( is_network_admin() ) {
203
				$plugins = array_filter( $plugins, 'is_plugin_active_for_network' );
204
			} else {
205
				$plugins = array_filter( $plugins, 'is_plugin_active' );
206
				$plugins = array_diff( $plugins, array_filter( $plugins, 'is_plugin_active_for_network' ) );
207
			}
208
			if ( empty($plugins) ) {
209
				wp_redirect( self_admin_url("plugins.php?plugin_status=$status&paged=$page&s=$s") );
210
				exit;
211
			}
212
213
			deactivate_plugins( $plugins, false, is_network_admin() );
214
215
			$deactivated = array();
216
			foreach ( $plugins as $plugin ) {
217
				$deactivated[ $plugin ] = time();
218
			}
219
220
			if ( ! is_network_admin() ) {
221
				update_option( 'recently_activated', $deactivated + (array) get_option( 'recently_activated' ) );
222
			} else {
223
				update_site_option( 'recently_activated', $deactivated + (array) get_site_option( 'recently_activated' ) );
224
			}
225
226
			wp_redirect( self_admin_url("plugins.php?deactivate-multi=true&plugin_status=$status&paged=$page&s=$s") );
227
			exit;
228
229
		case 'delete-selected':
230
			if ( ! current_user_can('delete_plugins') ) {
231
				wp_die(__('Sorry, you are not allowed to delete plugins for this site.'));
232
			}
233
234
			check_admin_referer('bulk-plugins');
235
236
			//$_POST = from the plugin form; $_GET = from the FTP details screen.
237
			$plugins = isset( $_REQUEST['checked'] ) ? (array) $_REQUEST['checked'] : array();
238
			if ( empty( $plugins ) ) {
239
				wp_redirect( self_admin_url("plugins.php?plugin_status=$status&paged=$page&s=$s") );
240
				exit;
241
			}
242
243
			$plugins = array_filter($plugins, 'is_plugin_inactive'); // Do not allow to delete Activated plugins.
244
			if ( empty( $plugins ) ) {
245
				wp_redirect( self_admin_url( "plugins.php?error=true&main=true&plugin_status=$status&paged=$page&s=$s" ) );
246
				exit;
247
			}
248
249
			// Bail on all if any paths are invalid.
250
			// validate_file() returns truthy for invalid files
251
			$invalid_plugin_files = array_filter( $plugins, 'validate_file' );
252
			if ( $invalid_plugin_files ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $invalid_plugin_files of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
253
				wp_redirect( self_admin_url("plugins.php?plugin_status=$status&paged=$page&s=$s") );
254
				exit;
255
			}
256
257
			include(ABSPATH . 'wp-admin/update.php');
258
259
			$parent_file = 'plugins.php';
260
261
			if ( ! isset($_REQUEST['verify-delete']) ) {
262
				wp_enqueue_script('jquery');
263
				require_once(ABSPATH . 'wp-admin/admin-header.php');
264
				?>
265
			<div class="wrap">
266
				<?php
267
					$plugin_info = array();
268
					$have_non_network_plugins = false;
269
					foreach ( (array) $plugins as $plugin ) {
270
						$plugin_slug = dirname( $plugin );
271
272
						if ( '.' == $plugin_slug ) {
273
							if ( $data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin ) ) {
274
								$plugin_info[ $plugin ] = $data;
275
								$plugin_info[ $plugin ]['is_uninstallable'] = is_uninstallable_plugin( $plugin );
276
								if ( ! $plugin_info[ $plugin ]['Network'] ) {
277
									$have_non_network_plugins = true;
278
								}
279
							}
280
						} else {
281
							// Get plugins list from that folder.
282
							if ( $folder_plugins = get_plugins( '/' . $plugin_slug ) ) {
283
								foreach ( $folder_plugins as $plugin_file => $data ) {
284
									$plugin_info[ $plugin_file ] = _get_plugin_data_markup_translate( $plugin_file, $data );
285
									$plugin_info[ $plugin_file ]['is_uninstallable'] = is_uninstallable_plugin( $plugin );
286
									if ( ! $plugin_info[ $plugin_file ]['Network'] ) {
287
										$have_non_network_plugins = true;
288
									}
289
								}
290
							}
291
						}
292
					}
293
					$plugins_to_delete = count( $plugin_info );
294
				?>
295
				<?php if ( 1 == $plugins_to_delete ) : ?>
296
					<h1><?php _e( 'Delete Plugin' ); ?></h1>
297
					<?php if ( $have_non_network_plugins && is_network_admin() ) : ?>
298
						<div class="error"><p><strong><?php _e( 'Caution:' ); ?></strong> <?php _e( 'This plugin may be active on other sites in the network.' ); ?></p></div>
299
					<?php endif; ?>
300
					<p><?php _e( 'You are about to remove the following plugin:' ); ?></p>
301
				<?php else: ?>
302
					<h1><?php _e( 'Delete Plugins' ); ?></h1>
303
					<?php if ( $have_non_network_plugins && is_network_admin() ) : ?>
304
						<div class="error"><p><strong><?php _e( 'Caution:' ); ?></strong> <?php _e( 'These plugins may be active on other sites in the network.' ); ?></p></div>
305
					<?php endif; ?>
306
					<p><?php _e( 'You are about to remove the following plugins:' ); ?></p>
307
				<?php endif; ?>
308
					<ul class="ul-disc">
309
						<?php
310
						$data_to_delete = false;
311
						foreach ( $plugin_info as $plugin ) {
312
							if ( $plugin['is_uninstallable'] ) {
313
								/* translators: 1: plugin name, 2: plugin author */
314
								echo '<li>', sprintf( __( '%1$s by %2$s (will also <strong>delete its data</strong>)' ), '<strong>' . $plugin['Name'] . '</strong>', '<em>' . $plugin['AuthorName'] . '</em>' ), '</li>';
315
								$data_to_delete = true;
316
							} else {
317
								/* translators: 1: plugin name, 2: plugin author */
318
								echo '<li>', sprintf( _x('%1$s by %2$s', 'plugin' ), '<strong>' . $plugin['Name'] . '</strong>', '<em>' . $plugin['AuthorName'] ) . '</em>', '</li>';
319
							}
320
						}
321
						?>
322
					</ul>
323
				<p><?php
324
				if ( $data_to_delete )
325
					_e('Are you sure you wish to delete these files and data?');
326
				else
327
					_e('Are you sure you wish to delete these files?');
328
				?></p>
329
				<form method="post" action="<?php echo esc_url($_SERVER['REQUEST_URI']); ?>" style="display:inline;">
0 ignored issues
show
It seems like $_SERVER['REQUEST_URI'] can also be of type boolean; however, esc_url() does only seem to accept string, 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...
330
					<input type="hidden" name="verify-delete" value="1" />
331
					<input type="hidden" name="action" value="delete-selected" />
332
					<?php
333
						foreach ( (array) $plugins as $plugin ) {
334
							echo '<input type="hidden" name="checked[]" value="' . esc_attr( $plugin ) . '" />';
335
						}
336
					?>
337
					<?php wp_nonce_field('bulk-plugins') ?>
338
					<?php submit_button( $data_to_delete ? __( 'Yes, delete these files and data' ) : __( 'Yes, delete these files' ), '', 'submit', false ); ?>
339
				</form>
340
				<?php
341
				$referer = wp_get_referer();
342
				?>
343
				<form method="post" action="<?php echo $referer ? esc_url( $referer ) : ''; ?>" style="display:inline;">
344
					<?php submit_button( __( 'No, return me to the plugin list' ), '', 'submit', false ); ?>
345
				</form>
346
			</div>
347
				<?php
348
				require_once(ABSPATH . 'wp-admin/admin-footer.php');
349
				exit;
350
			} else {
351
				$plugins_to_delete = count( $plugins );
352
			} // endif verify-delete
353
354
			$delete_result = delete_plugins( $plugins );
355
356
			set_transient('plugins_delete_result_' . $user_ID, $delete_result); //Store the result in a cache rather than a URL param due to object type & length
357
			wp_redirect( self_admin_url("plugins.php?deleted=$plugins_to_delete&plugin_status=$status&paged=$page&s=$s") );
358
			exit;
359
360
		case 'clear-recent-list':
361
			if ( ! is_network_admin() ) {
362
				update_option( 'recently_activated', array() );
363
			} else {
364
				update_site_option( 'recently_activated', array() );
365
			}
366
			break;
367
368 View Code Duplication
		default:
369
			if ( isset( $_POST['checked'] ) ) {
370
				check_admin_referer('bulk-plugins');
371
				$plugins = isset( $_POST['checked'] ) ? (array) $_POST['checked'] : array();
372
				$sendback = wp_get_referer();
373
374
				/** This action is documented in wp-admin/edit-comments.php */
375
				$sendback = apply_filters( 'handle_bulk_actions-' . get_current_screen()->id, $sendback, $action, $plugins );
376
				wp_safe_redirect( $sendback );
377
				exit;
378
			}
379
			break;
380
	}
381
382
}
383
384
$wp_list_table->prepare_items();
385
386
wp_enqueue_script('plugin-install');
387
add_thickbox();
388
389
add_screen_option( 'per_page', array( 'default' => 999 ) );
390
391
get_current_screen()->add_help_tab( array(
392
'id'		=> 'overview',
393
'title'		=> __('Overview'),
394
'content'	=>
395
	'<p>' . __('Plugins extend and expand the functionality of WordPress. Once a plugin is installed, you may activate it or deactivate it here.') . '</p>' .
396
	'<p>' . __( 'The search for installed plugins will search for terms in their name, description, or author.' ) . ' <span id="live-search-desc" class="hide-if-no-js">' . __( 'The search results will be updated as you type.' ) . '</span></p>' .
397
	'<p>' . sprintf(
398
		/* translators: %s: WordPress Plugin Directory URL */
399
		__( 'If you would like to see more plugins to choose from, click on the &#8220;Add New&#8221; button and you will be able to browse or search for additional plugins from the <a href="%s">WordPress Plugin Directory</a>. Plugins in the WordPress Plugin Directory are designed and developed by third parties, and are compatible with the license WordPress uses. Oh, and they&#8217;re free!' ),
400
		__( 'https://wordpress.org/plugins/' )
401
	) . '</p>'
402
) );
403
get_current_screen()->add_help_tab( array(
404
'id'		=> 'compatibility-problems',
405
'title'		=> __('Troubleshooting'),
406
'content'	=>
407
	'<p>' . __('Most of the time, plugins play nicely with the core of WordPress and with other plugins. Sometimes, though, a plugin&#8217;s code will get in the way of another plugin, causing compatibility issues. If your site starts doing strange things, this may be the problem. Try deactivating all your plugins and re-activating them in various combinations until you isolate which one(s) caused the issue.') . '</p>' .
408
	'<p>' . sprintf(
409
		/* translators: WP_PLUGIN_DIR constant value */
410
		__( 'If something goes wrong with a plugin and you can&#8217;t use WordPress, delete or rename that file in the %s directory and it will be automatically deactivated.' ),
411
		'<code>' . WP_PLUGIN_DIR . '</code>'
412
	) . '</p>'
413
) );
414
415
get_current_screen()->set_help_sidebar(
416
	'<p><strong>' . __('For more information:') . '</strong></p>' .
417
	'<p>' . __('<a href="https://codex.wordpress.org/Managing_Plugins#Plugin_Management">Documentation on Managing Plugins</a>') . '</p>' .
418
	'<p>' . __('<a href="https://wordpress.org/support/">Support Forums</a>') . '</p>'
419
);
420
421
get_current_screen()->set_screen_reader_content( array(
422
	'heading_views'      => __( 'Filter plugins list' ),
423
	'heading_pagination' => __( 'Plugins list navigation' ),
424
	'heading_list'       => __( 'Plugins list' ),
425
) );
426
427
$title = __('Plugins');
428
$parent_file = 'plugins.php';
429
430
require_once(ABSPATH . 'wp-admin/admin-header.php');
431
432
$invalid = validate_active_plugins();
433
if ( ! empty( $invalid ) ) {
434
	foreach ( $invalid as $plugin_file => $error ) {
435
		echo '<div id="message" class="error"><p>';
436
		printf(
437
			/* translators: 1: plugin file 2: error message */
438
			__( 'The plugin %1$s has been <strong>deactivated</strong> due to an error: %2$s' ),
439
			'<code>' . esc_html( $plugin_file ) . '</code>',
440
			$error->get_error_message() );
441
		echo '</p></div>';
442
	}
443
}
444
?>
445
446
<?php if ( isset($_GET['error']) ) :
447
448 View Code Duplication
	if ( isset( $_GET['main'] ) )
449
		$errmsg = __( 'You cannot delete a plugin while it is active on the main site.' );
450
	elseif ( isset($_GET['charsout']) )
451
		$errmsg = sprintf(__('The plugin generated %d characters of <strong>unexpected output</strong> during activation. If you notice &#8220;headers already sent&#8221; messages, problems with syndication feeds or other issues, try deactivating or removing this plugin.'), $_GET['charsout']);
452
	else
453
		$errmsg = __('Plugin could not be activated because it triggered a <strong>fatal error</strong>.');
454
	?>
455
	<div id="message" class="error"><p><?php echo $errmsg; ?></p>
456
	<?php
457
		if ( ! isset( $_GET['main'] ) && ! isset( $_GET['charsout'] ) && wp_verify_nonce( $_GET['_error_nonce'], 'plugin-activation-error_' . $plugin ) ) {
458
			$iframe_url = add_query_arg( array(
459
				'action'   => 'error_scrape',
460
				'plugin'   => urlencode( $plugin ),
461
				'_wpnonce' => urlencode( $_GET['_error_nonce'] ),
462
			), admin_url( 'plugins.php' ) );
463
		?>
464
		<iframe style="border:0" width="100%" height="70px" src="<?php echo esc_url( $iframe_url ); ?>"></iframe>
465
	<?php
466
		}
467
	?>
468
	</div>
469
<?php elseif ( isset($_GET['deleted']) ) :
470
		$delete_result = get_transient( 'plugins_delete_result_' . $user_ID );
471
		// Delete it once we're done.
472
		delete_transient( 'plugins_delete_result_' . $user_ID );
473
474
		if ( is_wp_error($delete_result) ) : ?>
475
		<div id="message" class="error notice is-dismissible"><p><?php printf( __('Plugin could not be deleted due to an error: %s'), $delete_result->get_error_message() ); ?></p></div>
476
		<?php else : ?>
477
		<div id="message" class="updated notice is-dismissible">
478
			<p>
479
				<?php
480
				if ( 1 == (int) $_GET['deleted'] ) {
481
					_e( 'The selected plugin has been <strong>deleted</strong>.' );
482
				} else {
483
					_e( 'The selected plugins have been <strong>deleted</strong>.' );
484
				}
485
				?>
486
			</p>
487
		</div>
488
		<?php endif; ?>
489
<?php elseif ( isset($_GET['activate']) ) : ?>
490
	<div id="message" class="updated notice is-dismissible"><p><?php _e('Plugin <strong>activated</strong>.') ?></p></div>
491
<?php elseif (isset($_GET['activate-multi'])) : ?>
492
	<div id="message" class="updated notice is-dismissible"><p><?php _e('Selected plugins <strong>activated</strong>.'); ?></p></div>
493
<?php elseif ( isset($_GET['deactivate']) ) : ?>
494
	<div id="message" class="updated notice is-dismissible"><p><?php _e('Plugin <strong>deactivated</strong>.') ?></p></div>
495
<?php elseif (isset($_GET['deactivate-multi'])) : ?>
496
	<div id="message" class="updated notice is-dismissible"><p><?php _e('Selected plugins <strong>deactivated</strong>.'); ?></p></div>
497
<?php elseif ( 'update-selected' == $action ) : ?>
498
	<div id="message" class="updated notice is-dismissible"><p><?php _e('All selected plugins are up to date.'); ?></p></div>
499
<?php endif; ?>
500
501
<div class="wrap">
502
<h1 class="wp-heading-inline"><?php
503
echo esc_html( $title );
504
?></h1>
505
506
<?php
507 View Code Duplication
if ( ( ! is_multisite() || is_network_admin() ) && current_user_can('install_plugins') ) { ?>
508
	<a href="<?php echo self_admin_url( 'plugin-install.php' ); ?>" class="page-title-action"><?php echo esc_html_x( 'Add New', 'plugin' ); ?></a>
509
<?php
510
}
511
512 View Code Duplication
if ( strlen( $s ) ) {
513
	/* translators: %s: search keywords */
514
	printf( '<span class="subtitle">' . __( 'Search results for &#8220;%s&#8221;' ) . '</span>', esc_html( urldecode( $s ) ) );
515
}
516
?>
517
518
<hr class="wp-header-end">
519
520
<?php
521
/**
522
 * Fires before the plugins list table is rendered.
523
 *
524
 * This hook also fires before the plugins list table is rendered in the Network Admin.
525
 *
526
 * Please note: The 'active' portion of the hook name does not refer to whether the current
527
 * view is for active plugins, but rather all plugins actively-installed.
528
 *
529
 * @since 3.0.0
530
 *
531
 * @param array $plugins_all An array containing all installed plugins.
532
 */
533
do_action( 'pre_current_active_plugins', $plugins['all'] );
534
?>
535
536
<?php $wp_list_table->views(); ?>
537
538
<form class="search-form search-plugins" method="get">
539
<?php $wp_list_table->search_box( __( 'Search Installed Plugins' ), 'plugin' ); ?>
540
</form>
541
542
<form method="post" id="bulk-action-form">
543
544
<input type="hidden" name="plugin_status" value="<?php echo esc_attr($status) ?>" />
545
<input type="hidden" name="paged" value="<?php echo esc_attr($page) ?>" />
546
547
<?php $wp_list_table->display(); ?>
548
</form>
549
550
	<span class="spinner"></span>
551
</div>
552
553
<?php
554
wp_print_request_filesystem_credentials_modal();
555
wp_print_admin_notice_templates();
556
wp_print_update_row_templates();
557
558
include(ABSPATH . 'wp-admin/admin-footer.php');
559