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-admin/includes/class-wp-users-list-table.php (1 issue)

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
 * List Table API: WP_Users_List_Table class
4
 *
5
 * @package WordPress
6
 * @subpackage Administration
7
 * @since 3.1.0
8
 */
9
10
/**
11
 * Core class used to implement displaying users in a list table.
12
 *
13
 * @since 3.1.0
14
 * @access private
15
 *
16
 * @see WP_List_Table
17
 */
18
class WP_Users_List_Table extends WP_List_Table {
19
20
	/**
21
	 * Site ID to generate the Users list table for.
22
	 *
23
	 * @since 3.1.0
24
	 * @access public
25
	 * @var int
26
	 */
27
	public $site_id;
28
29
	/**
30
	 * Whether or not the current Users list table is for Multisite.
31
	 *
32
	 * @since 3.1.0
33
	 * @access public
34
	 * @var bool
35
	 */
36
	public $is_site_users;
37
38
	/**
39
	 * Constructor.
40
	 *
41
	 * @since 3.1.0
42
	 * @access public
43
	 *
44
	 * @see WP_List_Table::__construct() for more information on default arguments.
45
	 *
46
	 * @param array $args An associative array of arguments.
47
	 */
48
	public function __construct( $args = array() ) {
49
		parent::__construct( array(
50
			'singular' => 'user',
51
			'plural'   => 'users',
52
			'screen'   => isset( $args['screen'] ) ? $args['screen'] : null,
53
		) );
54
55
		$this->is_site_users = 'site-users-network' === $this->screen->id;
56
57 View Code Duplication
		if ( $this->is_site_users )
58
			$this->site_id = isset( $_REQUEST['id'] ) ? intval( $_REQUEST['id'] ) : 0;
59
	}
60
61
	/**
62
	 * Check the current user's permissions.
63
	 *
64
 	 * @since 3.1.0
65
	 * @access public
66
	 *
67
	 * @return bool
68
	 */
69
	public function ajax_user_can() {
70
		if ( $this->is_site_users )
71
			return current_user_can( 'manage_sites' );
72
		else
73
			return current_user_can( 'list_users' );
74
	}
75
76
	/**
77
	 * Prepare the users list for display.
78
	 *
79
	 * @since 3.1.0
80
	 * @access public
81
	 *
82
	 * @global string $role
83
	 * @global string $usersearch
84
	 */
85
	public function prepare_items() {
86
		global $role, $usersearch;
87
88
		$usersearch = isset( $_REQUEST['s'] ) ? wp_unslash( trim( $_REQUEST['s'] ) ) : '';
89
90
		$role = isset( $_REQUEST['role'] ) ? $_REQUEST['role'] : '';
91
92
		$per_page = ( $this->is_site_users ) ? 'site_users_network_per_page' : 'users_per_page';
93
		$users_per_page = $this->get_items_per_page( $per_page );
94
95
		$paged = $this->get_pagenum();
96
97
		if ( 'none' === $role ) {
98
			$args = array(
99
				'number' => $users_per_page,
100
				'offset' => ( $paged-1 ) * $users_per_page,
101
				'include' => wp_get_users_with_no_role(),
102
				'search' => $usersearch,
103
				'fields' => 'all_with_meta'
104
			);
105
		} else {
106
			$args = array(
107
				'number' => $users_per_page,
108
				'offset' => ( $paged-1 ) * $users_per_page,
109
				'role' => $role,
110
				'search' => $usersearch,
111
				'fields' => 'all_with_meta'
112
			);
113
		}
114
115
		if ( '' !== $args['search'] )
116
			$args['search'] = '*' . $args['search'] . '*';
117
118
		if ( $this->is_site_users )
119
			$args['blog_id'] = $this->site_id;
120
121
		if ( isset( $_REQUEST['orderby'] ) )
122
			$args['orderby'] = $_REQUEST['orderby'];
123
124
		if ( isset( $_REQUEST['order'] ) )
125
			$args['order'] = $_REQUEST['order'];
126
127
		/**
128
		 * Filters the query arguments used to retrieve users for the current users list table.
129
		 *
130
		 * @since 4.4.0
131
		 *
132
		 * @param array $args Arguments passed to WP_User_Query to retrieve items for the current
133
		 *                    users list table.
134
		 */
135
		$args = apply_filters( 'users_list_table_query_args', $args );
136
137
		// Query the user IDs for this page
138
		$wp_user_search = new WP_User_Query( $args );
139
140
		$this->items = $wp_user_search->get_results();
141
142
		$this->set_pagination_args( array(
143
			'total_items' => $wp_user_search->get_total(),
144
			'per_page' => $users_per_page,
145
		) );
146
	}
147
148
	/**
149
	 * Output 'no users' message.
150
	 *
151
	 * @since 3.1.0
152
	 * @access public
153
	 */
154
	public function no_items() {
155
		_e( 'No users found.' );
156
	}
157
158
	/**
159
	 * Return an associative array listing all the views that can be used
160
	 * with this table.
161
	 *
162
	 * Provides a list of roles and user count for that role for easy
163
	 * Filtersing of the user table.
164
	 *
165
	 * @since  3.1.0
166
	 * @access protected
167
	 *
168
	 * @global string $role
169
	 *
170
	 * @return array An array of HTML links, one for each view.
171
	 */
172
	protected function get_views() {
173
		global $role;
174
175
		$wp_roles = wp_roles();
176
177
		if ( $this->is_site_users ) {
178
			$url = 'site-users.php?id=' . $this->site_id;
179
			switch_to_blog( $this->site_id );
180
			$users_of_blog = count_users();
181
			restore_current_blog();
182
		} else {
183
			$url = 'users.php';
184
			$users_of_blog = count_users();
185
		}
186
187
		$total_users = $users_of_blog['total_users'];
188
		$avail_roles =& $users_of_blog['avail_roles'];
189
		unset($users_of_blog);
190
191
		$class = empty($role) ? ' class="current"' : '';
192
		$role_links = array();
193
		$role_links['all'] = "<a href='$url'$class>" . sprintf( _nx( 'All <span class="count">(%s)</span>', 'All <span class="count">(%s)</span>', $total_users, 'users' ), number_format_i18n( $total_users ) ) . '</a>';
194
		foreach ( $wp_roles->get_names() as $this_role => $name ) {
195
			if ( !isset($avail_roles[$this_role]) )
196
				continue;
197
198
			$class = '';
199
200
			if ( $this_role === $role ) {
201
				$class = ' class="current"';
202
			}
203
204
			$name = translate_user_role( $name );
205
			/* translators: User role name with count */
206
			$name = sprintf( __('%1$s <span class="count">(%2$s)</span>'), $name, number_format_i18n( $avail_roles[$this_role] ) );
207
			$role_links[$this_role] = "<a href='" . esc_url( add_query_arg( 'role', $this_role, $url ) ) . "'$class>$name</a>";
208
		}
209
210
		if ( ! empty( $avail_roles['none' ] ) ) {
211
212
			$class = '';
213
214
			if ( 'none' === $role ) {
215
				$class = ' class="current"';
216
			}
217
218
			$name = __( 'No role' );
219
			/* translators: User role name with count */
220
			$name = sprintf( __('%1$s <span class="count">(%2$s)</span>'), $name, number_format_i18n( $avail_roles['none' ] ) );
221
			$role_links['none'] = "<a href='" . esc_url( add_query_arg( 'role', 'none', $url ) ) . "'$class>$name</a>";
222
223
		}
224
225
		return $role_links;
226
	}
227
228
	/**
229
	 * Retrieve an associative array of bulk actions available on this table.
230
	 *
231
	 * @since  3.1.0
232
	 * @access protected
233
	 *
234
	 * @return array Array of bulk actions.
235
	 */
236
	protected function get_bulk_actions() {
237
		$actions = array();
238
239
		if ( is_multisite() ) {
240
			if ( current_user_can( 'remove_users' ) )
241
				$actions['remove'] = __( 'Remove' );
242
		} else {
243
			if ( current_user_can( 'delete_users' ) )
244
				$actions['delete'] = __( 'Delete' );
245
		}
246
247
		return $actions;
248
	}
249
250
	/**
251
	 * Output the controls to allow user roles to be changed in bulk.
252
	 *
253
	 * @since 3.1.0
254
	 * @access protected
255
	 *
256
	 * @param string $which Whether this is being invoked above ("top")
257
	 *                      or below the table ("bottom").
258
	 */
259
	protected function extra_tablenav( $which ) {
260
		$id = 'bottom' === $which ? 'new_role2' : 'new_role';
261
	?>
262
	<div class="alignleft actions">
263
		<?php if ( current_user_can( 'promote_users' ) && $this->has_items() ) : ?>
264
		<label class="screen-reader-text" for="<?php echo $id ?>"><?php _e( 'Change role to&hellip;' ) ?></label>
265
		<select name="<?php echo $id ?>" id="<?php echo $id ?>">
266
			<option value=""><?php _e( 'Change role to&hellip;' ) ?></option>
267
			<?php wp_dropdown_roles(); ?>
268
		</select>
269
	<?php
270
			submit_button( __( 'Change' ), 'button', 'changeit', false );
271
		endif;
272
273
		/**
274
		 * Fires just before the closing div containing the bulk role-change controls
275
		 * in the Users list table.
276
		 *
277
		 * @since 3.5.0
278
		 * @since 4.6.0 The `$which` parameter was added.
279
		 *
280
		 * @param string $which The location of the extra table nav markup: 'top' or 'bottom'.
281
		 */
282
		do_action( 'restrict_manage_users', $which );
283
		echo '</div>';
284
	}
285
286
	/**
287
	 * Capture the bulk action required, and return it.
288
	 *
289
	 * Overridden from the base class implementation to capture
290
	 * the role change drop-down.
291
	 *
292
	 * @since  3.1.0
293
	 * @access public
294
	 *
295
	 * @return string The bulk action required.
296
	 */
297
	public function current_action() {
298
		if ( isset( $_REQUEST['changeit'] ) &&
299
			( ! empty( $_REQUEST['new_role'] ) || ! empty( $_REQUEST['new_role2'] ) ) ) {
300
			return 'promote';
301
		}
302
303
		return parent::current_action();
304
	}
305
306
	/**
307
	 * Get a list of columns for the list table.
308
	 *
309
	 * @since  3.1.0
310
	 * @access public
311
	 *
312
	 * @return array Array in which the key is the ID of the column,
313
	 *               and the value is the description.
314
	 */
315 View Code Duplication
	public function get_columns() {
316
		$c = array(
317
			'cb'       => '<input type="checkbox" />',
318
			'username' => __( 'Username' ),
319
			'name'     => __( 'Name' ),
320
			'email'    => __( 'Email' ),
321
			'role'     => __( 'Role' ),
322
			'posts'    => __( 'Posts' )
323
		);
324
325
		if ( $this->is_site_users )
326
			unset( $c['posts'] );
327
328
		return $c;
329
	}
330
331
	/**
332
	 * Get a list of sortable columns for the list table.
333
	 *
334
	 * @since 3.1.0
335
	 * @access protected
336
	 *
337
	 * @return array Array of sortable columns.
338
	 */
339
	protected function get_sortable_columns() {
340
		$c = array(
341
			'username' => 'login',
342
			'email'    => 'email',
343
		);
344
345
		return $c;
346
	}
347
348
	/**
349
	 * Generate the list table rows.
350
	 *
351
	 * @since 3.1.0
352
	 * @access public
353
	 */
354
	public function display_rows() {
355
		// Query the post counts for this page
356
		if ( ! $this->is_site_users )
357
			$post_counts = count_many_users_posts( array_keys( $this->items ) );
358
359
		foreach ( $this->items as $userid => $user_object ) {
360
			if ( is_multisite() && empty( $user_object->allcaps ) )
361
				continue;
362
363
			echo "\n\t" . $this->single_row( $user_object, '', '', isset( $post_counts ) ? $post_counts[ $userid ] : 0 );
364
		}
365
	}
366
367
	/**
368
	 * Generate HTML for a single row on the users.php admin panel.
369
	 *
370
	 * @since 3.1.0
371
	 * @since 4.2.0 The `$style` parameter was deprecated.
372
	 * @since 4.4.0 The `$role` parameter was deprecated.
373
	 * @access public
374
	 *
375
	 * @param object $user_object The current user object.
376
	 * @param string $style       Deprecated. Not used.
377
	 * @param string $role        Deprecated. Not used.
378
	 * @param int    $numposts    Optional. Post count to display for this user. Defaults
379
	 *                            to zero, as in, a new user has made zero posts.
380
	 * @return string Output for a single row.
381
	 */
382
	public function single_row( $user_object, $style = '', $role = '', $numposts = 0 ) {
383
		if ( ! ( $user_object instanceof WP_User ) ) {
384
			$user_object = get_userdata( (int) $user_object );
385
		}
386
		$user_object->filter = 'display';
387
		$email = $user_object->user_email;
388
389
		if ( $this->is_site_users )
390
			$url = "site-users.php?id={$this->site_id}&amp;";
391
		else
392
			$url = 'users.php?';
393
394
		$user_roles = $this->get_role_list( $user_object );
0 ignored issues
show
It seems like $user_object can also be of type false; however, WP_Users_List_Table::get_role_list() does only seem to accept object<WP_User>, did you maybe forget to handle an error condition?
Loading history...
395
396
		// Set up the hover actions for this user
397
		$actions = array();
398
		$checkbox = '';
399
		// Check if the user for this row is editable
400
		if ( current_user_can( 'list_users' ) ) {
401
			// Set up the user editing link
402
			$edit_link = esc_url( add_query_arg( 'wp_http_referer', urlencode( wp_unslash( $_SERVER['REQUEST_URI'] ) ), get_edit_user_link( $user_object->ID ) ) );
403
404
			if ( current_user_can( 'edit_user',  $user_object->ID ) ) {
405
				$edit = "<strong><a href=\"$edit_link\">$user_object->user_login</a></strong><br />";
406
				$actions['edit'] = '<a href="' . $edit_link . '">' . __( 'Edit' ) . '</a>';
407
			} else {
408
				$edit = "<strong>$user_object->user_login</strong><br />";
409
			}
410
411 View Code Duplication
			if ( !is_multisite() && get_current_user_id() != $user_object->ID && current_user_can( 'delete_user', $user_object->ID ) )
412
				$actions['delete'] = "<a class='submitdelete' href='" . wp_nonce_url( "users.php?action=delete&amp;user=$user_object->ID", 'bulk-users' ) . "'>" . __( 'Delete' ) . "</a>";
413 View Code Duplication
			if ( is_multisite() && get_current_user_id() != $user_object->ID && current_user_can( 'remove_user', $user_object->ID ) )
414
				$actions['remove'] = "<a class='submitdelete' href='" . wp_nonce_url( $url."action=remove&amp;user=$user_object->ID", 'bulk-users' ) . "'>" . __( 'Remove' ) . "</a>";
415
416
			/**
417
			 * Filters the action links displayed under each user in the Users list table.
418
			 *
419
			 * @since 2.8.0
420
			 *
421
			 * @param array   $actions     An array of action links to be displayed.
422
			 *                             Default 'Edit', 'Delete' for single site, and
423
			 *                             'Edit', 'Remove' for Multisite.
424
			 * @param WP_User $user_object WP_User object for the currently-listed user.
425
			 */
426
			$actions = apply_filters( 'user_row_actions', $actions, $user_object );
427
428
			// Role classes.
429
			$role_classes = esc_attr( implode( ' ', array_keys( $user_roles ) ) );
430
431
			// Set up the checkbox ( because the user is editable, otherwise it's empty )
432
			$checkbox = '<label class="screen-reader-text" for="user_' . $user_object->ID . '">' . sprintf( __( 'Select %s' ), $user_object->user_login ) . '</label>'
433
						. "<input type='checkbox' name='users[]' id='user_{$user_object->ID}' class='{$role_classes}' value='{$user_object->ID}' />";
434
435
		} else {
436
			$edit = '<strong>' . $user_object->user_login . '</strong>';
437
		}
438
		$avatar = get_avatar( $user_object->ID, 32 );
439
440
		// Comma-separated list of user roles.
441
		$roles_list = implode( ', ', $user_roles );
442
443
		$r = "<tr id='user-$user_object->ID'>";
444
445
		list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info();
446
447
		foreach ( $columns as $column_name => $column_display_name ) {
448
			$classes = "$column_name column-$column_name";
449
			if ( $primary === $column_name ) {
450
				$classes .= ' has-row-actions column-primary';
451
			}
452
			if ( 'posts' === $column_name ) {
453
				$classes .= ' num'; // Special case for that column
454
			}
455
456
			if ( in_array( $column_name, $hidden ) ) {
457
				$classes .= ' hidden';
458
			}
459
460
			$data = 'data-colname="' . wp_strip_all_tags( $column_display_name ) . '"';
461
462
			$attributes = "class='$classes' $data";
463
464
			if ( 'cb' === $column_name ) {
465
				$r .= "<th scope='row' class='check-column'>$checkbox</th>";
466
			} else {
467
				$r .= "<td $attributes>";
468
				switch ( $column_name ) {
469
					case 'username':
470
						$r .= "$avatar $edit";
471
						break;
472
					case 'name':
473
						$r .= "$user_object->first_name $user_object->last_name";
474
						break;
475
					case 'email':
476
						$r .= "<a href='" . esc_url( "mailto:$email" ) . "'>$email</a>";
477
						break;
478
					case 'role':
479
						$r .= esc_html( $roles_list );
480
						break;
481
					case 'posts':
482
						if ( $numposts > 0 ) {
483
							$r .= "<a href='edit.php?author=$user_object->ID' class='edit'>";
484
							$r .= '<span aria-hidden="true">' . $numposts . '</span>';
485
							$r .= '<span class="screen-reader-text">' . sprintf( _n( '%s post by this author', '%s posts by this author', $numposts ), number_format_i18n( $numposts ) ) . '</span>';
486
							$r .= '</a>';
487
						} else {
488
							$r .= 0;
489
						}
490
						break;
491
					default:
492
						/**
493
						 * Filters the display output of custom columns in the Users list table.
494
						 *
495
						 * @since 2.8.0
496
						 *
497
						 * @param string $output      Custom column output. Default empty.
498
						 * @param string $column_name Column name.
499
						 * @param int    $user_id     ID of the currently-listed user.
500
						 */
501
						$r .= apply_filters( 'manage_users_custom_column', '', $column_name, $user_object->ID );
502
				}
503
504
				if ( $primary === $column_name ) {
505
					$r .= $this->row_actions( $actions );
506
				}
507
				$r .= "</td>";
508
			}
509
		}
510
		$r .= '</tr>';
511
512
		return $r;
513
	}
514
515
	/**
516
	 * Gets the name of the default primary column.
517
	 *
518
	 * @since 4.3.0
519
	 * @access protected
520
	 *
521
	 * @return string Name of the default primary column, in this case, 'username'.
522
	 */
523
	protected function get_default_primary_column_name() {
524
		return 'username';
525
	}
526
527
	/**
528
	 * Returns an array of user roles for a given user object.
529
	 *
530
	 * @since 4.4.0
531
	 * @access protected
532
	 *
533
	 * @param WP_User $user_object The WP_User object.
534
	 * @return array An array of user roles.
535
	 */
536
	protected function get_role_list( $user_object ) {
537
		$wp_roles = wp_roles();
538
539
		$role_list = array();
540
541
		foreach ( $user_object->roles as $role ) {
542
			if ( isset( $wp_roles->role_names[ $role ] ) ) {
543
				$role_list[ $role ] = translate_user_role( $wp_roles->role_names[ $role ] );
544
			}
545
		}
546
547
		if ( empty( $role_list ) ) {
548
			$role_list['none'] = _x( 'None', 'no user roles' );
549
		}
550
551
		/**
552
		 * Filters the returned array of roles for a user.
553
		 *
554
		 * @since 4.4.0
555
		 *
556
		 * @param array   $role_list   An array of user roles.
557
		 * @param WP_User $user_object A WP_User object.
558
		 */
559
		return apply_filters( 'get_role_list', $role_list, $user_object );
560
	}
561
562
}
563