From 66f537e7023f9c46dd3bbe18e467f47994787be2 Mon Sep 17 00:00:00 2001 From: Gary Pendergast Date: Tue, 17 Jul 2018 07:21:50 +0000 Subject: [PATCH] REST API: Attachments controller should respect upload limits. When the REST API is in use on WordPress multisite, the `WP_REST_Attachments_Controller` should respect the "Max upload file size" and "Site upload space" site options. Props flixos90, danielbachhuber. Fixes #43751. git-svn-id: https://develop.svn.wordpress.org/trunk@43462 602fd350-edb4-49c9-b593-d223f7449a82 --- .../class-wp-rest-attachments-controller.php | 48 +++++++++ .../rest-api/rest-attachments-controller.php | 102 ++++++++++++++++++ 2 files changed, 150 insertions(+) diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php index 5854539a37..56c648e9bf 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php @@ -559,6 +559,11 @@ class WP_REST_Attachments_Controller extends WP_REST_Posts_Controller { 'type' => $type, ); + $size_check = self::check_upload_size( $file_data ); + if ( is_wp_error( $size_check ) ) { + return $size_check; + } + $overrides = array( 'test_form' => false, ); @@ -726,6 +731,11 @@ class WP_REST_Attachments_Controller extends WP_REST_Posts_Controller { $overrides['action'] = 'wp_handle_mock_upload'; } + $size_check = self::check_upload_size( $files['file'] ); + if ( is_wp_error( $size_check ) ) { + return $size_check; + } + /** Include admin functions to get access to wp_handle_upload() */ require_once ABSPATH . 'wp-admin/includes/admin.php'; @@ -763,4 +773,42 @@ class WP_REST_Attachments_Controller extends WP_REST_Posts_Controller { return $media_types; } + /** + * Determine if uploaded file exceeds space quota on multisite. + * + * Replicates check_upload_size(). + * + * @since 4.9.8 + * + * @param array $file $_FILES array for a given file. + * @return true|WP_Error True if can upload, error for errors. + */ + protected function check_upload_size( $file ) { + if ( ! is_multisite() ) { + return true; + } + + if ( get_site_option( 'upload_space_check_disabled' ) ) { + return true; + } + + $space_left = get_upload_space_available(); + + $file_size = filesize( $file['tmp_name'] ); + if ( $space_left < $file_size ) { + /* translators: %s: required disk space in kilobytes */ + return new WP_Error( 'rest_upload_limited_space', sprintf( __( 'Not enough space to upload. %s KB needed.' ), number_format( ( $file_size - $space_left ) / KB_IN_BYTES ) ), array( 'status' => 400 ) ); + } + + if ( $file_size > ( KB_IN_BYTES * get_site_option( 'fileupload_maxk', 1500 ) ) ) { + /* translators: %s: maximum allowed file size in kilobytes */ + return new WP_Error( 'rest_upload_file_too_big', sprintf( __( 'This file is too big. Files must be less than %s KB in size.' ), get_site_option( 'fileupload_maxk', 1500 ) ), array( 'status' => 400 ) ); + } + + if ( upload_is_user_over_quota( false ) ) { + return new WP_Error( 'rest_upload_user_quota_exceeded', __( 'You have used your space quota. Please delete files before uploading.' ), array( 'status' => 400 ) ); + } + return true; + } + } diff --git a/tests/phpunit/tests/rest-api/rest-attachments-controller.php b/tests/phpunit/tests/rest-api/rest-attachments-controller.php index 8803906f38..2131e03f41 100644 --- a/tests/phpunit/tests/rest-api/rest-attachments-controller.php +++ b/tests/phpunit/tests/rest-api/rest-attachments-controller.php @@ -1432,4 +1432,106 @@ class WP_Test_REST_Attachments_Controller extends WP_Test_REST_Post_Type_Control } + /** + * @ticket 43751 + * @group multisite + * @group ms-required + */ + public function test_create_item_with_file_exceeds_multisite_max_filesize() { + wp_set_current_user( self::$author_id ); + update_site_option( 'fileupload_maxk', 1 ); + update_site_option( 'upload_space_check_disabled', false ); + + $request = new WP_REST_Request( 'POST', '/wp/v2/media' ); + $request->set_file_params( + array( + 'file' => array( + 'error' => '0', + 'file' => file_get_contents( $this->test_file ), + 'name' => 'canola.jpg', + 'size' => filesize( $this->test_file ), + 'tmp_name' => $this->test_file, + ), + ) + ); + $request->set_param( 'title', 'My title is very cool' ); + $request->set_param( 'caption', 'This is a better caption.' ); + $request->set_header( 'Content-MD5', md5_file( $this->test_file ) ); + + $response = rest_get_server()->dispatch( $request ); + $this->assertErrorResponse( 'rest_upload_file_too_big', $response, 400 ); + } + + /** + * @ticket 43751 + * @group multisite + * @group ms-required + */ + public function test_create_item_with_data_exceeds_multisite_max_filesize() { + wp_set_current_user( self::$author_id ); + update_site_option( 'fileupload_maxk', 1 ); + update_site_option( 'upload_space_check_disabled', false ); + + $request = new WP_REST_Request( 'POST', '/wp/v2/media' ); + $request->set_header( 'Content-Type', 'image/jpeg' ); + $request->set_header( 'Content-Disposition', 'attachment; filename=canola.jpg' ); + $request->set_body( file_get_contents( $this->test_file ) ); + $request->set_param( 'title', 'My title is very cool' ); + $request->set_param( 'caption', 'This is a better caption.' ); + + $response = rest_get_server()->dispatch( $request ); + $this->assertErrorResponse( 'rest_upload_file_too_big', $response, 400 ); + } + + /** + * @ticket 43751 + * @group multisite + * @group ms-required + */ + public function test_create_item_with_file_exceeds_multisite_site_upload_space() { + wp_set_current_user( self::$author_id ); + add_filter( 'get_space_allowed', '__return_zero' ); + update_site_option( 'upload_space_check_disabled', false ); + + $request = new WP_REST_Request( 'POST', '/wp/v2/media' ); + $request->set_file_params( + array( + 'file' => array( + 'error' => '0', + 'file' => file_get_contents( $this->test_file ), + 'name' => 'canola.jpg', + 'size' => filesize( $this->test_file ), + 'tmp_name' => $this->test_file, + ), + ) + ); + $request->set_param( 'title', 'My title is very cool' ); + $request->set_param( 'caption', 'This is a better caption.' ); + $request->set_header( 'Content-MD5', md5_file( $this->test_file ) ); + + $response = rest_get_server()->dispatch( $request ); + $this->assertErrorResponse( 'rest_upload_limited_space', $response, 400 ); + } + + /** + * @ticket 43751 + * @group multisite + * @group ms-required + */ + public function test_create_item_with_data_exceeds_multisite_site_upload_space() { + wp_set_current_user( self::$author_id ); + add_filter( 'get_space_allowed', '__return_zero' ); + update_site_option( 'upload_space_check_disabled', false ); + + $request = new WP_REST_Request( 'POST', '/wp/v2/media' ); + $request->set_header( 'Content-Type', 'image/jpeg' ); + $request->set_header( 'Content-Disposition', 'attachment; filename=canola.jpg' ); + $request->set_body( file_get_contents( $this->test_file ) ); + $request->set_param( 'title', 'My title is very cool' ); + $request->set_param( 'caption', 'This is a better caption.' ); + + $response = rest_get_server()->dispatch( $request ); + $this->assertErrorResponse( 'rest_upload_limited_space', $response, 400 ); + } + }