Make WordPress Core

Changeset 56865

Timestamp:
10/12/2023 02:51:26 PM (9 months ago)
Author:
davidbaumwald
Message:

Grouped backports to the 4.9 branch.

  • Comments: Prevent users who can not see a post from seeing comments on it.
  • Shortcodes: Restrict media shortcode ajax to certain type.
  • REST API: Ensure no-cache headers are sent when methods are overridden.
  • REST API: Limit search_columns for users without list_users.
  • Prevent unintended behavior when certain objects are unserialized.

Merges [56834], [56835], [56836], [56838], and [56840] to the 4.9 branch.
Props xknown, jorbin, joehoyle, timothyblynjacobs, peterwilsoncc, ehtis, tykoted, antpb, rmccue.

Location:
branches/4.9/src
Files:
13 edited

Legend:

Unmodified
Added
Removed
  • branches/4.9/src/wp-admin/includes/ajax-actions.php

    r55787 r56865  
    31413141    $shortcode = wp_unslash( $_POST['shortcode'] );
    31423142
     3143
     3144
     3145
     3146
     3147
     3148
     3149
     3150
     3151
     3152
     3153
     3154
     3155
     3156
     3157
     3158
    31433159    if ( ! empty( $_POST['post_ID'] ) ) {
    31443160        $post = get_post( (int) $_POST['post_ID'] );
     
    31473163    // the embed shortcode requires a post
    31483164    if ( ! $post || ! current_user_can( 'edit_post', $post->ID ) ) {
    3149         if ( 'embed' === $shortcode ) {
     3165        if ( ) {
    31503166            wp_send_json_error();
    31513167        }
  • branches/4.9/src/wp-admin/includes/class-wp-comments-list-table.php

    r41683 r56865  
    501501        $this->user_can = current_user_can( 'edit_comment', $comment->comment_ID );
    502502
     503
     504
     505
     506
     507
     508
     509
     510
     511
     512
     513
     514
     515
    503516        echo "<tr id='comment-$comment->comment_ID' class='$the_comment_class'>";
    504517        $this->single_row_columns( $comment );
  • branches/4.9/src/wp-admin/includes/class-wp-list-table.php

    r41161 r56865  
    623623        $pending_phrase = sprintf( _n( '%s pending comment', '%s pending comments', $pending_comments ), $pending_comments_number );
    624624
    625         // No comments at all.
     625        $post_object   = get_post( $post_id );
     626        $edit_post_cap = $post_object ? 'edit_post' : 'edit_posts';
     627        if (
     628            current_user_can( $edit_post_cap, $post_id ) ||
     629            (
     630                empty( $post_object->post_password ) &&
     631                current_user_can( 'read_post', $post_id )
     632            )
     633        ) {
     634            // The user has access to the post and thus can see comments
     635        } else {
     636            return false;
     637        }
     638
    626639        if ( ! $approved_comments && ! $pending_comments ) {
    627640            printf( '<span aria-hidden="true">&#8212;</span><span class="screen-reader-text">%s</span>',
  • branches/4.9/src/wp-admin/includes/dashboard.php

    r44106 r56865  
    920920
    921921        echo '<ul id="the-comment-list" data-wp-lists="list:comment">';
    922         foreach ( $comments as $comment )
    923             _wp_dashboard_recent_comments_row( $comment );
     922        foreach ( $comments as $comment ) {
     923            $comment_post = get_post( $comment->comment_post_ID );
     924            if (
     925                current_user_can( 'edit_post', $comment->comment_post_ID ) ||
     926                (
     927                    empty( $comment_post->post_password ) &&
     928                    current_user_can( 'read_post', $comment->comment_post_ID )
     929                )
     930            ) {
     931                _wp_dashboard_recent_comments_row( $comment );
     932            }
     933        }
    924934        echo '</ul>';
    925935
  • branches/4.9/src/wp-includes/Requests/Hooks.php

    r38049 r56865  
    6666        return true;
    6767    }
     68
     69
     70
     71
    6872}
  • branches/4.9/src/wp-includes/Requests/IRI.php

    r38727 r56865  
    704704    }
    705705
     706
     707
     708
     709
     710
     711
     712
     713
     714
     715
     716
     717
     718
     719
    706720    /**
    707721     * Set the entire IRI. Returns true on success, false on failure (if there
  • branches/4.9/src/wp-includes/Requests/Session.php

    r38049 r56865  
    228228    }
    229229
     230
     231
     232
     233
    230234    /**
    231235     * Merge a request's data with the default data
  • branches/4.9/src/wp-includes/class-wp-theme.php

    r43028 r56865  
    536536
    537537    /**
     538
     539
     540
     541
     542
     543
     544
     545
     546
     547
     548
     549
     550
     551
     552
     553
     554
     555
     556
     557
     558
     559
    538560     * Adds theme data to cache.
    539561     *
     
    14871509        return strnatcasecmp( $a->display( 'Name', false, true ), $b->display( 'Name', false, true ) );
    14881510    }
     1511
     1512
     1513
     1514
     1515
     1516
     1517
     1518
     1519
     1520
     1521
     1522
    14891523}
  • branches/4.9/src/wp-includes/media.php

    r55787 r56865  
    16881688        }
    16891689    } elseif ( ! empty( $atts['exclude'] ) ) {
     1690
    16901691        $attachments = get_children( array( 'post_parent' => $id, 'exclude' => $atts['exclude'], 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $atts['order'], 'orderby' => $atts['orderby'] ) );
    16911692    } else {
     1693
    16921694        $attachments = get_children( array( 'post_parent' => $id, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $atts['order'], 'orderby' => $atts['orderby'] ) );
     1695
     1696
     1697
     1698
     1699
     1700
     1701
     1702
     1703
     1704
     1705
    16931706    }
    16941707
     
    19922005    }
    19932006
     2007
     2008
     2009
     2010
     2011
     2012
     2013
     2014
     2015
    19942016    if ( empty( $attachments ) ) {
    19952017        return '';
  • branches/4.9/src/wp-includes/rest-api.php

    r46493 r56865  
    784784
    785785    if ( ! $result ) {
     786
    786787        return new WP_Error( 'rest_cookie_invalid_nonce', __( 'Cookie nonce is invalid' ), array( 'status' => 403 ) );
    787788    }
  • branches/4.9/src/wp-includes/rest-api/class-wp-rest-server.php

    r42422 r56865  
    236236
    237237        /**
    238          * Send nocache headers on authenticated requests.
     238         * .
    239239         *
    240240         * @since 4.4.0
     241
     242
     243
     244
     245
     246
     247
     248
     249
     250
     251
     252
     253
     254
     255
     256
     257
     258
     259
     260
     261
     262
     263
     264
     265
     266
     267
     268
     269
     270
     271
     272
     273
     274
     275
     276
     277
     278
     279
     280
     281
     282
     283
     284
     285
     286
     287
     288
     289
     290
     291
     292
     293
     294
     295
     296
     297
     298
     299
     300
     301
     302
     303
     304
     305
     306
     307
     308
     309
     310
     311
     312
     313
     314
     315
     316
     317
     318
     319
     320
     321
     322
     323
     324
     325
     326
     327
     328
     329
     330
     331
     332
     333
     334
     335
     336
     337
     338
     339
     340
     341
     342
     343
     344
     345
     346
     347
     348
     349
     350
     351
     352
     353
     354
     355
     356
     357
     358
     359
     360
     361
     362
    241363         *
    242364         * @param bool $rest_send_nocache_headers Whether to send no-cache headers.
    243365         */
    244366        $send_no_cache_headers = apply_filters( 'rest_send_nocache_headers', is_user_logged_in() );
    245         if ( $send_no_cache_headers ) {
     367
     368        // send no cache headers if the $send_no_cache_headers is true
     369        // OR if the HTTP_X_HTTP_METHOD_OVERRIDE is used but resulted a 4xx response code.
     370        if ( $send_no_cache_headers || ( true === $method_overridden && strpos( $code, '4' ) === 0 ) ) {
    246371            foreach ( wp_get_nocache_headers() as $header => $header_value ) {
    247372                if ( empty( $header_value ) ) {
     
    252377            }
    253378        }
    254 
    255         /**
    256          * Filters whether the REST API is enabled.
    257          *
    258          * @since 4.4.0
    259          * @deprecated 4.7.0 Use the rest_authentication_errors filter to restrict access to the API
    260          *
    261          * @param bool $rest_enabled Whether the REST API is enabled. Default true.
    262          */
    263         apply_filters_deprecated( 'rest_enabled', array( true ), '4.7.0', 'rest_authentication_errors',
    264             __( 'The REST API can no longer be completely disabled, the rest_authentication_errors filter can be used to restrict access to the API, instead.' )
    265         );
    266 
    267         /**
    268          * Filters whether jsonp is enabled.
    269          *
    270          * @since 4.4.0
    271          *
    272          * @param bool $jsonp_enabled Whether jsonp is enabled. Default true.
    273          */
    274         $jsonp_enabled = apply_filters( 'rest_jsonp_enabled', true );
    275 
    276         $jsonp_callback = null;
    277 
    278         if ( isset( $_GET['_jsonp'] ) ) {
    279             if ( ! $jsonp_enabled ) {
    280                 echo $this->json_error( 'rest_callback_disabled', __( 'JSONP support is disabled on this site.' ), 400 );
    281                 return false;
    282             }
    283 
    284             $jsonp_callback = $_GET['_jsonp'];
    285             if ( ! wp_check_jsonp_callback( $jsonp_callback ) ) {
    286                 echo $this->json_error( 'rest_callback_invalid', __( 'Invalid JSONP callback function.' ), 400 );
    287                 return false;
    288             }
    289         }
    290 
    291         if ( empty( $path ) ) {
    292             if ( isset( $_SERVER['PATH_INFO'] ) ) {
    293                 $path = $_SERVER['PATH_INFO'];
    294             } else {
    295                 $path = '/';
    296             }
    297         }
    298 
    299         $request = new WP_REST_Request( $_SERVER['REQUEST_METHOD'], $path );
    300 
    301         $request->set_query_params( wp_unslash( $_GET ) );
    302         $request->set_body_params( wp_unslash( $_POST ) );
    303         $request->set_file_params( $_FILES );
    304         $request->set_headers( $this->get_headers( wp_unslash( $_SERVER ) ) );
    305         $request->set_body( $this->get_raw_data() );
    306 
    307         /*
    308          * HTTP method override for clients that can't use PUT/PATCH/DELETE. First, we check
    309          * $_GET['_method']. If that is not set, we check for the HTTP_X_HTTP_METHOD_OVERRIDE
    310          * header.
    311          */
    312         if ( isset( $_GET['_method'] ) ) {
    313             $request->set_method( $_GET['_method'] );
    314         } elseif ( isset( $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] ) ) {
    315             $request->set_method( $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] );
    316         }
    317 
    318         $result = $this->check_authentication();
    319 
    320         if ( ! is_wp_error( $result ) ) {
    321             $result = $this->dispatch( $request );
    322         }
    323 
    324         // Normalize to either WP_Error or WP_REST_Response...
    325         $result = rest_ensure_response( $result );
    326 
    327         // ...then convert WP_Error across.
    328         if ( is_wp_error( $result ) ) {
    329             $result = $this->error_to_response( $result );
    330         }
    331 
    332         /**
    333          * Filters the API response.
    334          *
    335          * Allows modification of the response before returning.
    336          *
    337          * @since 4.4.0
    338          * @since 4.5.0 Applied to embedded responses.
    339          *
    340          * @param WP_HTTP_Response $result  Result to send to the client. Usually a WP_REST_Response.
    341          * @param WP_REST_Server   $this    Server instance.
    342          * @param WP_REST_Request  $request Request used to generate the response.
    343          */
    344         $result = apply_filters( 'rest_post_dispatch', rest_ensure_response( $result ), $this, $request );
    345 
    346         // Wrap the response in an envelope if asked for.
    347         if ( isset( $_GET['_envelope'] ) ) {
    348             $result = $this->envelope_response( $result, isset( $_GET['_embed'] ) );
    349         }
    350 
    351         // Send extra data from response objects.
    352         $headers = $result->get_headers();
    353         $this->send_headers( $headers );
    354 
    355         $code = $result->get_status();
    356         $this->set_status( $code );
    357 
    358         /**
    359          * Filters whether the request has already been served.
    360          *
    361          * Allow sending the request manually - by returning true, the API result
    362          * will not be sent to the client.
    363          *
    364          * @since 4.4.0
    365          *
    366          * @param bool             $served  Whether the request has already been served.
    367          *                                           Default false.
    368          * @param WP_HTTP_Response $result  Result to send to the client. Usually a WP_REST_Response.
    369          * @param WP_REST_Request  $request Request used to generate the response.
    370          * @param WP_REST_Server   $this    Server instance.
    371          */
    372         $served = apply_filters( 'rest_pre_serve_request', false, $result, $request, $this );
    373379
    374380        if ( ! $served ) {
  • branches/4.9/src/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php

    r43445 r56865  
    272272
    273273        if ( ! empty( $prepared_args['search'] ) ) {
     274
     275
     276
    274277            $prepared_args['search'] = '*' . $prepared_args['search'] . '*';
    275278        }
  • branches/4.9/src/wp-includes/shortcodes.php

    r41286 r56865  
    160160
    161161/**
    162  * Search content for shortcodes and filter shortcodes through their hooks.
     162 * Returns a list of registered shortcode names found in the given content.
     163 *
     164 * Example usage:
     165 *
     166 *     get_shortcode_tags_in_content( '[audio src="file.mp3"][/audio] [foo] [gallery ids="1,2,3"]' );
     167 *     // array( 'audio', 'gallery' )
     168 *
     169 * @since 6.3.2
     170 *
     171 * @param string $content The content to check.
     172 * @return string[] An array of registered shortcode names found in the content.
     173 */
     174function get_shortcode_tags_in_content( $content ) {
     175    if ( false === strpos( $content, '[' ) ) {
     176        return array();
     177    }
     178
     179    preg_match_all( '/' . get_shortcode_regex() . '/', $content, $matches, PREG_SET_ORDER );
     180    if ( empty( $matches ) ) {
     181        return array();
     182    }
     183
     184    $tags = array();
     185    foreach ( $matches as $shortcode ) {
     186        $tags[] = $shortcode[2];
     187
     188        if ( ! empty( $shortcode[5] ) ) {
     189            $deep_tags = get_shortcode_tags_in_content( $shortcode[5] );
     190            if ( ! empty( $deep_tags ) ) {
     191                $tags = array_merge( $tags, $deep_tags );
     192            }
     193        }
     194    }
     195
     196    return $tags;
     197}
     198
     199/**
     200 * Searches content for shortcodes and filter shortcodes through their hooks.
    163201 *
    164202 * If there are no shortcode tags defined, then the content will be returned
Note: See TracChangeset for help on using the changeset viewer.