Make WordPress Core


Ignore:
Timestamp:
10/12/2023 02:59:28 PM (3 years ago)
Author:
davidbaumwald
Message:

Grouped backports to the 5.0 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 [56833], [56834], [56835], [56836], and [56838] to the 5.0 branch.
Props xknown, jorbin, joehoyle, timothyblynjacobs, peterwilsoncc, ehtis, tykoted, antpb, rmccue.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/5.0/src/wp-includes/rest-api/class-wp-rest-server.php

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