Ticket #6278: 6278.08.patch
File 6278.08.patch, 20.0 KB (added by , 10 years ago) |
---|
-
src/bp-core/bp-core-avatars.php
diff --git src/bp-core/bp-core-avatars.php src/bp-core/bp-core-avatars.php index 44fe3c3..d7aa748 100644
function bp_core_check_avatar_size( $file ) { 782 782 } 783 783 784 784 /** 785 * Get allowed avatar types/mimes 786 * 787 * @since BuddyPress (2.3.0) 788 * 789 * @param bool $mimes whether to get the mimes or extensions. 790 * @uses apply_filters() call 'bp_core_get_allowed_avatar_type' to restrict the types 791 * @return array the list of allowed avatar types (mimes or extensions). 792 */ 793 function bp_core_get_allowed_avatar_types( $mimes = false ) { 794 $no_new_types = array( 795 'jpg' => 0, 796 'gif' => 1, 797 'png' => 2, 798 ); 799 800 /** 801 * Use this filter to restrict image types 802 * 803 * @since BuddyPress (2.3.0) 804 * 805 * @param array list of image types (eg: array( 'jpg', 'gif', 'png')); 806 */ 807 $avatar_types = (array) apply_filters( 'bp_core_get_allowed_avatar_types', array_keys( $no_new_types ) ); 808 809 if ( empty( $avatar_types ) ) { 810 $allowed_types = $no_new_types; 811 } else { 812 $allowed_types = array_intersect_key( $no_new_types, array_flip( $avatar_types ) ); 813 } 814 815 $avatar_types = array_flip( $allowed_types ); 816 817 // If no mime is needed, return a list of allowed extensions 818 if ( empty( $mimes ) ) { 819 return $avatar_types; 820 821 // Return an array containing the list of allowed mimes 822 } else { 823 $allowed_mimes = $allowed_types; 824 825 // Transpose JPG to WordPress mime 826 if ( isset( $allowed_mimes['jpg'] ) ) { 827 $allowed_mimes['jpg|jpeg|jpe'] = $allowed_mimes['jpg']; 828 } 829 830 return array_intersect_key( array( 831 'jpg|jpeg|jpe' => 'image/jpeg', 832 'gif' => 'image/gif', 833 'png' => 'image/png', 834 ), $allowed_mimes ); 835 } 836 } 837 838 /** 785 839 * Does the current avatar upload have an allowed file type? 786 840 * 787 841 * Permitted file types are JPG, GIF and PNG. 788 842 * 789 843 * @param array $file The $_FILES array. 844 * @uses bp_core_get_allowed_avatar_type() 845 * @uses wp_check_filetype() 790 846 * @return bool True if the file extension is permitted, otherwise false. 791 847 */ 792 function bp_core_check_avatar_type($file) { 793 if ( ( !empty( $file['file']['type'] ) && !preg_match('/(jpe?g|gif|png)$/i', $file['file']['type'] ) ) || !preg_match( '/(jpe?g|gif|png)$/i', $file['file']['name'] ) ) 794 return false; 848 function bp_core_check_avatar_type( $file ) { 849 $allowed_mimes = bp_core_get_allowed_avatar_types( true ); 850 851 // Try with the file name 852 if ( ! empty( $file['file']['name'] ) ) { 853 $is_allowed = wp_check_filetype( $file['file']['name'], $allowed_mimes ); 854 return ! empty( $is_allowed['ext'] ); 855 856 // Try with the file type 857 } else if ( ! empty( $file['file']['type'] ) ) { 858 $is_allowed = array_flip( $allowed_mimes ); 859 return isset( $is_allowed[ $file['file']['type'] ] ); 860 } 795 861 796 return true;862 return false; 797 863 } 798 864 799 865 /** -
src/bp-core/classes/class-bp-attachment-avatar.php
diff --git src/bp-core/classes/class-bp-attachment-avatar.php src/bp-core/classes/class-bp-attachment-avatar.php index 8940954..074235b 100644
class BP_Attachment_Avatar extends BP_Attachment { 35 35 36 36 // Specific errors for avatars 37 37 'upload_error_strings' => array( 38 9 => sprintf( __( 'That photo is too big. Please upload one smaller than %s ', 'buddypress' ), size_format( bp_core_avatar_original_max_filesize() ) ),39 10 => __( 'Please upload only JPG, GIF or PNG photos.', 'buddypress'),38 9 => sprintf( __( 'That photo is too big. Please upload one smaller than %s.', 'buddypress' ), size_format( bp_core_avatar_original_max_filesize() ) ), 39 10 => sprintf( __( 'Please upload only these file types: %s.', 'buddypress' ), $this->get_avatar_types() ), 40 40 ), 41 41 ) ); 42 42 } 43 43 44 44 /** 45 * Gets the available avatar types 46 * 47 * @since BuddyPress (2.3.0) 48 * 49 * @uses bp_core_get_allowed_avatar_types() 50 * @return string comma separated list of allowed avatar types 51 */ 52 public function get_avatar_types() { 53 $types = array_map( 'strtoupper', bp_core_get_allowed_avatar_types() ); 54 return join( ', ', $types ); 55 } 56 57 /** 45 58 * Set Upload Dir data for avatars 46 59 * 47 60 * @since BuddyPress (2.3.0) -
src/bp-core/classes/class-bp-attachment.php
diff --git src/bp-core/classes/class-bp-attachment.php src/bp-core/classes/class-bp-attachment.php index 337c27f..e6a7bc4 100644
defined( 'ABSPATH' ) || exit; 16 16 * 17 17 * @since BuddyPress (2.3.0) 18 18 */ 19 class BP_Attachment {19 abstract class BP_Attachment { 20 20 21 21 /** Upload properties *****************************************************/ 22 22 … … class BP_Attachment { 28 28 public $attachment = array(); 29 29 30 30 /** 31 * Maximum file size in kilobytes 32 * 33 * @var int 34 */ 35 public $original_max_filesize = 0; 36 37 /** 38 * List of allowed file extensions 39 * Defaults to get_allowed_mime_types() 40 * 41 * @var int 42 */ 43 public $allowed_mime_types = array(); 44 45 /** 46 * component's upload base directory. 47 * 48 * @var string 49 */ 50 public $base_dir = ''; 51 52 /** 53 * The upload action. 54 * 55 * @var string 56 */ 57 public $action = ''; 58 59 /** 60 * The file input name attribute 61 * 62 * @var string 63 */ 64 public $file_input = ''; 65 66 /** 67 * List of upload errors. 68 * 69 * @var array 70 */ 71 public $upload_error_strings = array(); 72 73 /** 74 * List of required core files 31 * The default args to be merged with the 32 * ones passed by the child class 75 33 * 76 34 * @var array 77 35 */ 78 public $required_wp_files = array( 'file' ); 36 protected $default_args = array( 37 'original_max_filesize' => 0, 38 'allowed_mime_types' => array(), 39 'base_dir' => '', 40 'action' => '', 41 'file_input' => '', 42 'upload_error_strings' => array(), 43 'required_wp_files' => array( 'file' ), 44 ); 79 45 80 46 /** 81 47 * Construct Upload parameters … … class BP_Attachment { 113 79 * Max file size defaults to php ini settings or, in the case of 114 80 * a multisite config, the root site fileupload_maxk option 115 81 */ 116 $this-> original_max_filesize= (int) wp_max_upload_size();82 $this->default_args['original_max_filesize'] = (int) wp_max_upload_size(); 117 83 118 $params = bp_parse_args( $args, get_class_vars( __CLASS__ ), $this->action . '_upload_params' );84 $params = bp_parse_args( $args, $this->default_args, $this->action . '_upload_params' ); 119 85 120 86 foreach ( $params as $key => $param ) { 121 87 if ( 'upload_error_strings' === $key ) { 122 88 $this->{$key} = $this->set_upload_error_strings( $param ); 123 } else { 89 90 // Sanitize the base dir 91 } else if ( 'base_dir' === $key ) { 92 $this->{$key} = sanitize_title( $param ); 93 94 // Action & File input are already set and sanitized 95 } else if ( 'action' != $key && 'file_input' != $key ) { 124 96 $this->{$key} = $param; 125 97 } 126 98 } … … class BP_Attachment { 395 367 } 396 368 397 369 // Check if upload path already exists 398 if ( ! file_exists( $this->upload_path ) ) {370 if ( ! is_dir( $this->upload_path ) ) { 399 371 400 372 // If path does not exist, attempt to create it 401 373 if ( ! wp_mkdir_p( $this->upload_path ) ) { … … class BP_Attachment { 429 401 public function crop( $args = array() ) { 430 402 $wp_error = new WP_Error(); 431 403 432 $r = wp_parse_args( $args, array(404 $r = bp_parse_args( $args, array( 433 405 'original_file' => '', 434 406 'crop_x' => 0, 435 407 'crop_y' => 0, … … class BP_Attachment { 439 411 'dst_h' => 0, 440 412 'src_abs' => false, 441 413 'dst_file' => false, 442 ) );414 ), 'bp_attachment_crop_args' ); 443 415 444 416 if ( empty( $r['original_file'] ) || ! file_exists( $r['original_file'] ) ) { 445 417 $wp_error->add( 'crop_error', __( 'Cropping the file failed: missing source file.', 'buddypress' ) ); -
tests/phpunit/assets/attachment-extensions.php
diff --git tests/phpunit/assets/attachment-extensions.php tests/phpunit/assets/attachment-extensions.php index e69de29..117b456 100644
1 <?php 2 /** 3 * The following implementations of BP_Attachment act as dummy plugins 4 * for our unit tests 5 */ 6 class BP_Attachment_Extend extends BP_Attachment { 7 public function __construct( $args = array() ) { 8 return parent::__construct( $args ); 9 } 10 } -
tests/phpunit/testcases/core/class-bp-attachment-avatar.php
diff --git tests/phpunit/testcases/core/class-bp-attachment-avatar.php tests/phpunit/testcases/core/class-bp-attachment-avatar.php index e69de29..c95921c 100644
1 <?php 2 3 /** 4 * @group core 5 * @group avatars 6 * @group bp_attachments 7 * @group BP_Attachement_Avatar 8 */ 9 class BP_Tests_BP_Attachement_Avatar_TestCases extends BP_UnitTestCase { 10 protected $displayed_user; 11 12 public function setUp() { 13 parent::setUp(); 14 $bp = buddypress(); 15 $this->displayed_user = $bp->displayed_user; 16 $bp->displayed_user = new stdClass; 17 } 18 19 public function tearDown() { 20 parent::tearDown(); 21 buddypress()->displayed_user = $this->displayed_user; 22 } 23 24 public function max_filesize() { 25 return 1000; 26 } 27 28 private function clean_avatars( $type = 'user' ) { 29 if ( 'user' === $type ) { 30 $avatar_dir = 'avatars'; 31 } elseif ( 'group' === $type ) { 32 $avatar_dir = 'group-avatars'; 33 } 34 35 $this->rrmdir( bp_core_avatar_upload_path() . '/' . $avatar_dir ); 36 } 37 38 private function rrmdir( $dir ) { 39 $d = glob( $dir . '/*' ); 40 41 if ( empty( $d ) ) { 42 return; 43 } 44 45 foreach ( $d as $file ) { 46 if ( is_dir( $file ) ) { 47 $this->rrmdir( $file ); 48 } else { 49 @unlink( $file ); 50 } 51 } 52 53 @rmdir( $dir ); 54 } 55 56 /** 57 * @group upload 58 */ 59 public function test_upload_user_avatar_no_error() { 60 $reset_files = $_FILES; 61 $reset_post = $_POST; 62 63 $u1 = $this->factory->user->create(); 64 buddypress()->displayed_user->id = $u1; 65 66 $avatar = BP_TESTS_DIR . 'assets/files/disc.png'; 67 68 $tmp_name = wp_tempnam( $avatar ); 69 70 copy( $avatar, $tmp_name ); 71 72 // Upload the file 73 $avatar_attachment = new BP_Attachment_Avatar(); 74 $_POST['action'] = $avatar_attachment->action; 75 $_FILES[ $avatar_attachment->file_input ] = array( 76 'tmp_name' => $tmp_name, 77 'name' => 'disc.png', 78 'type' => 'image/png', 79 'error' => 0, 80 'size' => filesize( $avatar ) 81 ); 82 83 $user_avatar = $avatar_attachment->upload( $_FILES, 'xprofile_avatar_upload_dir' ); 84 85 $this->assertTrue( empty( $user_avatar['error'] ) ); 86 87 // clean up! 88 $this->clean_avatars(); 89 $_FILES = $reset_files; 90 $_POST = $reset_post; 91 } 92 93 /** 94 * @group upload 95 */ 96 public function test_upload_group_avatar_no_error() { 97 $bp = buddypress(); 98 $reset_files = $_FILES; 99 $reset_post = $_POST; 100 $reset_current_group = $bp->groups->current_group; 101 102 $g = $this->factory->group->create(); 103 104 $bp->groups->current_group = groups_get_group( array( 105 'group_id' => $g, 106 'populate_extras' => true, 107 ) ); 108 109 $avatar = BP_TESTS_DIR . 'assets/files/disc.png'; 110 111 $tmp_name = wp_tempnam( $avatar ); 112 113 copy( $avatar, $tmp_name ); 114 115 // Upload the file 116 $avatar_attachment = new BP_Attachment_Avatar(); 117 $_POST['action'] = $avatar_attachment->action; 118 $_FILES[ $avatar_attachment->file_input ] = array( 119 'tmp_name' => $tmp_name, 120 'name' => 'disc.png', 121 'type' => 'image/png', 122 'error' => 0, 123 'size' => filesize( $avatar ) 124 ); 125 126 $group_avatar = $avatar_attachment->upload( $_FILES, 'groups_avatar_upload_dir' ); 127 128 $this->assertTrue( empty( $group_avatar['error'] ) ); 129 130 // clean up! 131 $this->clean_avatars( 'group' ); 132 $bp->groups->current_group = $reset_current_group; 133 $_FILES = $reset_files; 134 $_POST = $reset_post; 135 } 136 137 /** 138 * @group upload 139 */ 140 public function test_upload_user_avatar_file_size_error() { 141 $reset_files = $_FILES; 142 $reset_post = $_POST; 143 144 $u1 = $this->factory->user->create(); 145 buddypress()->displayed_user->id = $u1; 146 147 $avatar = BP_TESTS_DIR . 'assets/files/disc.png'; 148 149 $tmp_name = wp_tempnam( $avatar ); 150 151 copy( $avatar, $tmp_name ); 152 153 add_filter( 'bp_core_avatar_original_max_filesize', array( $this, 'max_filesize' ) ); 154 155 // Upload the file 156 $avatar_attachment = new BP_Attachment_Avatar(); 157 158 $_POST['action'] = $avatar_attachment->action; 159 $_FILES[ $avatar_attachment->file_input ] = array( 160 'tmp_name' => $tmp_name, 161 'name' => 'disc.png', 162 'type' => 'image/png', 163 'error' => 0, 164 'size' => filesize( $avatar ) 165 ); 166 167 $user_avatar = $avatar_attachment->upload( $_FILES, 'xprofile_avatar_upload_dir' ); 168 169 remove_filter( 'bp_core_avatar_original_max_filesize', array( $this, 'max_filesize' ) ); 170 171 $this->assertFalse( empty( $user_avatar['error'] ) ); 172 173 // clean up! 174 $_FILES = $reset_files; 175 $_POST = $reset_post; 176 } 177 178 /** 179 * @group upload 180 */ 181 public function test_upload_user_avatar_file_type_error() { 182 $reset_files = $_FILES; 183 $reset_post = $_POST; 184 185 $u1 = $this->factory->user->create(); 186 buddypress()->displayed_user->id = $u1; 187 188 $avatar = BP_TESTS_DIR . 'assets/files/buddypress_logo.pdf'; 189 190 $tmp_name = wp_tempnam( $avatar ); 191 192 copy( $avatar, $tmp_name ); 193 194 // Upload the file 195 $avatar_attachment = new BP_Attachment_Avatar(); 196 $_POST['action'] = $avatar_attachment->action; 197 $_FILES[ $avatar_attachment->file_input ] = array( 198 'tmp_name' => $tmp_name, 199 'name' => 'buddypress_logo.pdf', 200 'type' => 'application/pdf', 201 'error' => 0, 202 'size' => filesize( $avatar ) 203 ); 204 205 $user_avatar = $avatar_attachment->upload( $_FILES, 'xprofile_avatar_upload_dir' ); 206 207 $this->assertFalse( empty( $user_avatar['error'] ) ); 208 209 // clean up! 210 $_FILES = $reset_files; 211 $_POST = $reset_post; 212 } 213 214 /** 215 * @group crop 216 */ 217 public function test_crop_avatar() { 218 $avatar = BP_TESTS_DIR . 'assets/files/logo.jpg'; 219 $pdf = BP_TESTS_DIR . 'assets/files/buddypress_logo.pdf'; 220 221 $u1 = $this->factory->user->create(); 222 223 $upload_dir = xprofile_avatar_upload_dir( 'avatars', $u1 ); 224 225 wp_mkdir_p( $upload_dir['path'] ); 226 227 copy( $avatar, $upload_dir['path'] . '/logo.jpg' ); 228 copy( $pdf, $upload_dir['path'] . '/buddypress_logo.pdf' ); 229 230 $crop_args = array( 231 'object' => 'user', 232 'avatar_dir' => 'avatars', 233 'item_id' => $u1, 234 'original_file' => '/avatars/' . $u1 . '/logo.jpg', 235 ); 236 237 $avatar_attachment = new BP_Attachment_Avatar(); 238 $cropped = $avatar_attachment->crop( $crop_args ); 239 240 $this->assertTrue( ! empty( $cropped['full'] ) && ! is_wp_error( $cropped['full'] ) ); 241 242 $crop_args['original_file'] = '/avatars/' . $u1 . '/buddypress_logo.pdf'; 243 244 $cropped = $avatar_attachment->crop( $crop_args ); 245 $this->assertTrue( is_wp_error( $cropped['full'] ) ); 246 247 // Clean up 248 $this->clean_avatars(); 249 } 250 } -
tests/phpunit/testcases/core/class-bp-attachment.php
diff --git tests/phpunit/testcases/core/class-bp-attachment.php tests/phpunit/testcases/core/class-bp-attachment.php index e69de29..f0cc053 100644
1 <?php 2 3 include_once BP_TESTS_DIR . '/assets/attachment-extensions.php'; 4 5 /** 6 * @group bp_attachments 7 * @group BP_Attachement 8 */ 9 class BP_Tests_BP_Attachment_TestCases extends BP_UnitTestCase { 10 11 private function clean_files( $basedir = 'attachment_base_dir' ) { 12 $upload_dir = bp_upload_dir(); 13 14 $this->rrmdir( $upload_dir['basedir'] . '/' . $basedir ); 15 } 16 17 private function rrmdir( $dir ) { 18 $d = glob( $dir . '/*' ); 19 20 if ( empty( $d ) ) { 21 return; 22 } 23 24 foreach ( $d as $file ) { 25 if ( is_dir( $file ) ) { 26 $this->rrmdir( $file ); 27 } else { 28 @unlink( $file ); 29 } 30 } 31 32 @rmdir( $dir ); 33 } 34 35 public function test_construct_missing_required_parameter() { 36 $reset_files = $_FILES; 37 $reset_post = $_POST; 38 39 $_FILES['file'] = array( 40 'name' => 'disc.png', 41 'type' => 'image/png', 42 'error' => 0, 43 'size' => 10000 44 ); 45 46 $attachment_class = new BP_Attachment_Extend(); 47 $upload = $attachment_class->upload( $_FILES ); 48 49 $this->assertTrue( empty( $upload ) ); 50 51 $_FILES = $reset_files; 52 $_POST = $reset_post; 53 } 54 55 public function test_set_upload_dir() { 56 $upload_dir = bp_upload_dir(); 57 58 $attachment_class = new BP_Attachment_Extend( array( 59 'action' => 'attachment_action', 60 'file_input' => 'attachment_file_input' 61 ) ); 62 63 $this->assertSame( $attachment_class->upload_dir, bp_upload_dir() ); 64 65 $attachment_class = new BP_Attachment_Extend( array( 66 'action' => 'attachment_action', 67 'file_input' => 'attachment_file_input', 68 'base_dir' => 'attachment_base_dir', 69 ) ); 70 71 $this->assertTrue( file_exists( $upload_dir['basedir'] . '/attachment_base_dir' ) ); 72 73 // clean up 74 $this->clean_files(); 75 } 76 77 /** 78 * @group upload 79 */ 80 public function test_upload() { 81 $reset_files = $_FILES; 82 $reset_post = $_POST; 83 84 $file = BP_TESTS_DIR . 'assets/files/disc.png'; 85 86 $tmp_name = wp_tempnam( $file ); 87 88 copy( $file, $tmp_name ); 89 90 $attachment_class = new BP_Attachment_Extend( array( 91 'action' => 'attachment_action', 92 'file_input' => 'attachment_file_input', 93 'base_dir' => 'attachment_base_dir', 94 'original_max_filesize' => 10000, 95 ) ); 96 97 $_POST['action'] = $attachment_class->action; 98 $_FILES[ $attachment_class->file_input ] = array( 99 'tmp_name' => $tmp_name, 100 'name' => 'disc.png', 101 'type' => 'image/png', 102 'error' => 0, 103 'size' => filesize( $file ) 104 ); 105 106 // Error: file size 107 $upload = $attachment_class->upload( $_FILES ); 108 $this->assertFalse( empty( $upload['error'] ) ); 109 110 $attachment_class->allowed_mime_types = array( 'pdf' ); 111 $attachment_class->original_max_filesize = false; 112 113 // Error: file type 114 $upload = $attachment_class->upload( $_FILES ); 115 $this->assertFalse( empty( $upload['error'] ) ); 116 117 $attachment_class->allowed_mime_types = array(); 118 119 // Success 120 $upload = $attachment_class->upload( $_FILES ); 121 $this->assertTrue( empty( $upload['error'] ) ); 122 123 // clean up! 124 $_FILES = $reset_files; 125 $_POST = $reset_post; 126 $this->clean_files(); 127 } 128 129 /** 130 * @group crop 131 */ 132 public function test_crop_image() { 133 $image = BP_TESTS_DIR . 'assets/files/logo.jpg'; 134 135 $crop_args = array( 136 'original_file' => $image, 137 'crop_x' => 0, 138 'crop_y' => 0, 139 'crop_w' => 150, 140 'crop_h' => 150, 141 'dst_w' => 150, 142 'dst_h' => 150, 143 ); 144 145 $attachment_class = new BP_Attachment_Extend( array( 146 'action' => 'attachment_action', 147 'file_input' => 'attachment_file_input', 148 'base_dir' => 'attachment_base_dir', 149 ) ); 150 $cropped = $attachment_class->crop( $crop_args ); 151 152 // Image must come from the upload basedir 153 $this->assertTrue( is_wp_error( $cropped ) ); 154 155 $crop_args['original_file'] = $attachment_class->upload_path . '/logo.jpg'; 156 157 // Move to the base upload dir 158 copy( $image, $crop_args['original_file'] ); 159 160 // Image must stay in the upload basedir 161 $crop_args['dst_file'] = BP_TESTS_DIR . 'assets/files/error.jpg'; 162 $cropped = $attachment_class->crop( $crop_args ); 163 164 // Image must stay in the upload basedir 165 $this->assertTrue( is_wp_error( $cropped ) ); 166 167 unset( $crop_args['dst_file'] ); 168 169 $cropped = $attachment_class->crop( $crop_args ); 170 $this->assertFalse( is_wp_error( $cropped ) ); 171 172 // clean up! 173 $this->clean_files(); 174 } 175 } -
tests/phpunit/testcases/core/functions.php
diff --git tests/phpunit/testcases/core/functions.php tests/phpunit/testcases/core/functions.php index 1ab3b45..d165739 100644
class BP_Tests_Core_Functions extends BP_UnitTestCase { 572 572 date_default_timezone_set( $tz_backup ); 573 573 } 574 574 } 575 576 /** 577 * @group bp_attachments 578 * @group bp_upload_dir 579 */ 580 public function test_bp_upload_dir_ms() { 581 if ( ! is_multisite() ) { 582 return; 583 } 584 585 $expected_upload_dir = wp_upload_dir(); 586 587 $b = $this->factory->blog->create(); 588 589 switch_to_blog( $b ); 590 591 $tested_upload_dir = bp_upload_dir(); 592 593 restore_current_blog(); 594 595 $this->assertSame( $expected_upload_dir, $tested_upload_dir ); 596 } 575 597 }