diff --git a/src/wp-includes/functions.php b/src/wp-includes/functions.php index 86cdabe7e0..0bb42018f9 100644 --- a/src/wp-includes/functions.php +++ b/src/wp-includes/functions.php @@ -2989,6 +2989,15 @@ function wp_die( $message = '', $title = '', $args = array() ) { * @param callable $function Callback function name. */ $function = apply_filters( 'wp_die_json_handler', '_json_wp_die_handler' ); + } elseif ( wp_is_jsonp_request() ) { + /** + * Filters the callback for killing WordPress execution for JSONP requests. + * + * @since 5.2.0 + * + * @param callable $function Callback function name. + */ + $function = apply_filters( 'wp_die_jsonp_handler', '_jsonp_wp_die_handler' ); } elseif ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST ) { /** * Filters the callback for killing WordPress execution for XML-RPC requests. @@ -3247,6 +3256,48 @@ function _json_wp_die_handler( $message, $title = '', $args = array() ) { } } +/** + * Kill WordPress execution and display JSONP message with error message. + * + * This is the handler for wp_die when processing JSONP requests. + * + * @since 5.2.0 + * @access private + * + * @param string $message Error message. + * @param string $title Optional. Error title. Default empty. + * @param string|array $args Optional. Arguments to control behavior. Default empty array. + */ +function _jsonp_wp_die_handler( $message, $title = '', $args = array() ) { + list( $message, $title, $r ) = _wp_die_process_input( $message, $title, $args ); + + $data = array( + 'code' => $r['code'], + 'message' => $message, + 'data' => array( + 'status' => $r['response'], + ), + 'additional_errors' => $r['additional_errors'], + ); + + if ( ! headers_sent() ) { + header( 'Content-Type: application/javascript; charset=utf-8' ); + header( 'X-Content-Type-Options: nosniff' ); + header( 'X-Robots-Tag: noindex' ); + if ( null !== $r['response'] ) { + status_header( $r['response'] ); + } + nocache_headers(); + } + + $result = wp_json_encode( $data ); + $jsonp_callback = $_GET['_jsonp']; + echo '/**/' . $jsonp_callback . '(' . $result . ')'; + if ( $r['exit'] ) { + die(); + } +} + /** * Kills WordPress execution and displays XML response with an error message. * diff --git a/src/wp-includes/load.php b/src/wp-includes/load.php index b3c3762684..eba596ed1b 100644 --- a/src/wp-includes/load.php +++ b/src/wp-includes/load.php @@ -1501,3 +1501,31 @@ function wp_is_json_request() { return false; } + +/** + * Checks whether current request is a JSONP request, or is expecting a JSONP response. + * + * @since 5.2.0 + * + * @return bool True if JSONP request, false otherwise. + */ +function wp_is_jsonp_request() { + if ( ! isset( $_GET['_jsonp'] ) ) { + return false; + } + + if ( ! function_exists( 'wp_check_jsonp_callback' ) ) { + require_once ABSPATH . WPINC . '/functions.php'; + } + + $jsonp_callback = $_GET['_jsonp']; + if ( ! wp_check_jsonp_callback( $jsonp_callback ) ) { + return false; + } + + /** This filter is documented in wp-includes/rest-api/class-wp-rest-server.php */ + $jsonp_enabled = apply_filters( 'rest_jsonp_enabled', true ); + + return $jsonp_enabled; + +}