PluginProbe
Stream – Activity Log & Audit Trail / 3.7.0
Stream – Activity Log & Audit Trail v3.7.0
4.4.0 4.3.0 4.2.2 4.2.1 trunk 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.1 3.1.1 3.10.0 3.2.0 3.2.1 3.2.2 3.2.3 All 50 releases
← All changes | classes/class-network.php +41 -86 trunk3.7.0 View file →
@@ -26,13 +26,13 @@
26 26 */
27 27 public $network_settings_page_slug = 'wp_stream_network_settings';
28 28
29 29 /**
30 - * The option name for the network settings.
30 + * Default setting page slug
31 31 *
32 32 * @var string
33 33 */
34 - public $network_settings_option = 'wp_stream_network';
34 + public $default_settings_page_slug = 'wp_stream_default_settings';
35 35
36 36 /**
37 37 * Class constructor
38 38 *
@@ -83,21 +83,14 @@
83 83 *
84 84 * @see https://core.trac.wordpress.org/ticket/22589
85 85 */
86 86 public function ajax_network_admin() {
87 - $http_referer = isset( $_SERVER['HTTP_REFERER'] ) ? esc_url_raw( wp_unslash( $_SERVER['HTTP_REFERER'] ) ) : '';
88 -
89 - // Prefer filterable `wp_doing_ajax()` (WP 4.7+); the plugin supports 4.6.
90 - $doing_ajax = function_exists( 'wp_doing_ajax' )
91 - ? wp_doing_ajax()
92 - : ( defined( 'DOING_AJAX' ) && DOING_AJAX );
93 -
94 87 if (
95 - $doing_ajax
88 + defined( 'DOING_AJAX' )
96 89 &&
97 - 0 === stripos( $http_referer, network_admin_url() )
90 + DOING_AJAX
98 91 &&
99 - $this->can_view_network_records()
92 + preg_match( '#^' . network_admin_url() . '#i', $_SERVER['HTTP_REFERER'] )
100 93 ) {
101 94 define( 'WP_NETWORK_ADMIN', true );
102 95 return WP_NETWORK_ADMIN;
103 96 }
@@ -105,36 +98,8 @@
105 98 return false;
106 99 }
107 100
108 101 /**
109 - * Whether the current user is allowed to read records across the whole
110 - * network (and to be treated as being in the Network Admin).
111 - *
112 - * The Referer prefix checked in ajax_network_admin() is caller-controlled,
113 - * so it can only ever be a UI hint about where a request came from -- never
114 - * a source of authority. Network-wide record access additionally requires a
115 - * real network capability, otherwise a site-level Stream viewer could spoof
116 - * the header to lift the per-blog restriction applied in
117 - * network_query_args() or to have their actions logged against blog_id 0.
118 - *
119 - * @return bool
120 - */
121 - public function can_view_network_records() {
122 - if ( ! is_multisite() ) {
123 - return false;
124 - }
125 -
126 - // WP-CLI runs with shell-level access and usually with no logged-in
127 - // user, so capability checks would fail for a legitimate operator and
128 - // break `wp stream query --blog_id=N`. It sits outside this boundary.
129 - if ( defined( 'WP_CLI' ) && WP_CLI ) {
130 - return true;
131 - }
132 -
133 - return current_user_can( 'manage_network_options' );
134 - }
135 -
136 - /**
137 102 * Builds a stdClass object used when displaying actions done in network administration
138 103 *
139 104 * @return object
140 105 */
@@ -259,10 +224,15 @@
259 224 }
260 225
261 226 $current_page = wp_stream_filter_input( INPUT_GET, 'page' );
262 227
263 - if ( $this->network_settings_page_slug === $current_page ) {
264 - $description = __( 'These settings apply to all sites on the network.', 'stream' );
228 + switch ( $current_page ) {
229 + case $this->network_settings_page_slug:
230 + $description = __( 'These settings apply to all sites on the network.', 'stream' );
231 + break;
232 + case $this->default_settings_page_slug:
233 + $description = __( 'These default settings will apply to new sites created on the network. These settings do not alter existing sites.', 'stream' );
234 + break;
265 235 }
266 236
267 237 return $description;
268 238 }
@@ -380,50 +350,48 @@
380 350 /**
381 351 * Wrapper for the settings API to work on the network settings page
382 352 */
383 353 public function network_options_action() {
354 + $allowed_referers = array(
355 + $this->network_settings_page_slug,
356 + $this->default_settings_page_slug,
357 + );
384 358
385 - // Check the nonce.
386 - if (
387 - empty( $_POST['_wpnonce'] )
388 - ||
389 - ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ) ), sprintf( '%s-options', $this->network_settings_option ) )
390 - ) {
359 + // @codingStandardsIgnoreLine
360 + if ( ! isset( $_GET['action'] ) || ! in_array( $_GET['action'], $allowed_referers, true ) ) {
391 361 return;
392 362 }
393 363
394 - // Check the user capability.
395 - if ( ! current_user_can( $this->plugin->admin->settings_cap ) ) {
396 - return;
397 - }
364 + // @codingStandardsIgnoreLine
365 + $options = isset( $_POST['option_page'] ) ? explode( ',', stripslashes( $_POST['option_page'] ) ) : null;
398 366
399 - // Check the action.
400 - $action = isset( $_GET['action'] ) ? sanitize_key( wp_unslash( $_GET['action'] ) ) : '';
401 - if ( $this->network_settings_page_slug !== $action ) {
402 - return;
403 - }
367 + if ( $options ) {
404 368
405 - $option = ! empty( $_POST['option_page'] ) ? sanitize_key( wp_unslash( $_POST['option_page'] ) ) : false;
369 + foreach ( $options as $option ) {
370 + $option = trim( $option );
371 + $value = null;
372 + $sections = $this->plugin->settings->get_fields();
406 373
407 - if ( $option && $this->network_settings_option === $option ) {
374 + foreach ( $sections as $section_name => $section ) {
375 + foreach ( $section['fields'] as $field_idx => $field ) {
376 + $option_key = $section_name . '_' . $field['name'];
408 377
409 - $value = array();
410 - $posted_options = isset( $_POST[ $option ] ) && is_array( $_POST[ $option ] ) ? wp_unslash( $_POST[ $option ] ) : array();
411 - $sections = $this->plugin->settings->get_fields();
378 + // @codingStandardsIgnoreStart
379 + if ( isset( $_POST[ $option ][ $option_key ] ) ) {
380 + $value[ $option_key ] = $_POST[ $option ][ $option_key ];
381 + } else {
382 + $value[ $option_key ] = false;
383 + }
384 + // @codingStandardsIgnoreEnd
385 + }
386 + }
412 387
413 - foreach ( $sections as $section_name => $section ) {
414 - foreach ( $section['fields'] as $field_idx => $field ) {
415 - $option_key = $section_name . '_' . $field['name'];
388 + if ( ! is_array( $value ) ) {
389 + $value = trim( $value );
390 + }
416 391
417 - if ( isset( $posted_options[ $option_key ] ) ) {
418 - $value[ $option_key ] = $this->plugin->settings->sanitize_setting_by_field_type( $posted_options[ $option_key ], $field['type'] );
419 - } else {
420 - $value[ $option_key ] = false;
421 - }
422 - }
392 + update_site_option( $option, $value );
423 393 }
424 -
425 - update_site_option( $this->network_settings_option, $value );
426 394 }
427 395
428 396 if ( ! count( get_settings_errors() ) ) {
429 397 add_settings_error( 'general', 'settings_updated', __( 'Settings saved.', 'stream' ), 'updated' );
@@ -533,21 +501,8 @@
533 501 * @return array
534 502 */
535 503 public function network_query_args( $args ) {
536 504 $args['site_id'] = is_numeric( $args['site_id'] ) ? $args['site_id'] : get_current_site()->id;
537 -
538 - // Only users with a network capability may choose which blog to read
539 - // from. For everyone else the requested blog_id is ignored entirely and
540 - // forced to the current blog: a numeric type check is not an
541 - // authorization check, and the Stream tables are shared across the
542 - // whole network, so honouring an arbitrary ?blog_id= would let a
543 - // site-level viewer read another site's activity.
544 - if ( ! $this->can_view_network_records() ) {
545 - $args['blog_id'] = get_current_blog_id();
546 -
547 - return $args;
548 - }
549 -
550 505 $args['blog_id'] = is_numeric( $args['blog_id'] ) ? $args['blog_id'] : ( is_network_admin() ? null : get_current_blog_id() );
551 506
552 507 return $args;
553 508 }