Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
0.00% |
0 / 88 |
|
0.00% |
0 / 3 |
CRAP | n/a |
0 / 0 |
|
| wpcomsh_check_upload_size | |
0.00% |
0 / 14 |
|
0.00% |
0 / 1 |
90 | |||
| wpcomsh_jetpack_upload_handler_can_upload | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
30 | |||
| wpcomsh_allow_file_uploads_with_invalid_mime_types | |
0.00% |
0 / 63 |
|
0.00% |
0 / 1 |
702 | |||
| 1 | <?php |
| 2 | /** |
| 3 | * Filters related to disk storage for WordPress on Atomic. |
| 4 | * |
| 5 | * @package wpcomsh |
| 6 | */ |
| 7 | |
| 8 | /** |
| 9 | * Determine if uploaded file exceeds space quota. |
| 10 | * Modeled after core's check_upload_size() for multisite, but specific for WordPress on Atomic. |
| 11 | * |
| 12 | * @param array $file An element from the `$_FILES` array for a given file. |
| 13 | * @return array The `$_FILES` array element with 'error' key set if file exceeds quota. 'error' is empty otherwise. |
| 14 | */ |
| 15 | function wpcomsh_check_upload_size( $file ) { |
| 16 | if ( $file['error'] > 0 ) { // There's already an error. |
| 17 | return $file; |
| 18 | } |
| 19 | |
| 20 | if ( defined( 'WP_IMPORTING' ) ) { |
| 21 | return $file; |
| 22 | } |
| 23 | |
| 24 | $site_info = wpcomsh_get_at_site_info(); |
| 25 | if ( empty( $site_info['space_used'] ) || empty( $site_info['space_quota'] ) ) { |
| 26 | return $file; |
| 27 | } |
| 28 | |
| 29 | $space_available = $site_info['space_quota'] - $site_info['space_used']; |
| 30 | $file_size = filesize( $file['tmp_name'] ); |
| 31 | |
| 32 | if ( $file_size >= $space_available ) { |
| 33 | $file['error'] = __( 'You have used your space quota. Please delete files before uploading.', 'wpcomsh' ); |
| 34 | } |
| 35 | |
| 36 | if ( $file['error'] > 0 && ! isset( $_POST['html-upload'] ) && ! wp_doing_ajax() ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing |
| 37 | wp_die( esc_html( $file['error'] ), '', array( 'back_link' => true ) ); |
| 38 | } |
| 39 | |
| 40 | return $file; |
| 41 | } |
| 42 | add_filter( 'wp_handle_upload_prefilter', 'wpcomsh_check_upload_size' ); |
| 43 | |
| 44 | /** |
| 45 | * Do not allow uploads from Calypso's media section if it would cause our |
| 46 | * disk usage to go over the quota. |
| 47 | * |
| 48 | * @param bool|WP_Error $allowed If false or WP_Error, blocks the upload. If true, allows the upload. |
| 49 | * @param array $files The $_FILES attempting to be uploaded. |
| 50 | * |
| 51 | * @return bool|WP_Error WP_Error when uploaded file would exceed upload space, $allowed when not. |
| 52 | */ |
| 53 | function wpcomsh_jetpack_upload_handler_can_upload( $allowed, $files ) { |
| 54 | $site_info = wpcomsh_get_at_site_info(); |
| 55 | |
| 56 | if ( empty( $site_info['space_used'] ) || empty( $site_info['space_quota'] ) ) { |
| 57 | return $allowed; |
| 58 | } |
| 59 | |
| 60 | if ( ! empty( $files['media']['size'] ) ) { |
| 61 | $upload_size = array_sum( $files['media']['size'] ); |
| 62 | if ( $site_info['space_used'] + $upload_size > $site_info['space_quota'] ) { |
| 63 | return new WP_Error( 'insufficient_space_available', 'Uploaded file is too large.' ); |
| 64 | } |
| 65 | } |
| 66 | |
| 67 | return $allowed; |
| 68 | } |
| 69 | add_filter( 'jetpack_upload_handler_can_upload', 'wpcomsh_jetpack_upload_handler_can_upload', 10, 2 ); |
| 70 | |
| 71 | /** |
| 72 | * Allow the additional mime types that WPCOM already allows. |
| 73 | * |
| 74 | * @param array $file_data { |
| 75 | * Values for the extension, mime type, and corrected filename. |
| 76 | * |
| 77 | * @type string|false $ext File extension, or false if the file doesn't match a mime type. |
| 78 | * @type string|false $type File mime type, or false if the file doesn't match a mime type. |
| 79 | * @type string|false $proper_filename File name with its correct extension, or false if it cannot be determined. |
| 80 | * } |
| 81 | * @param string $file Full path to the file. |
| 82 | * @param string $filename The name of the file (may differ from $file due to |
| 83 | * $file being in a tmp directory). |
| 84 | * @param string[] $mimes Array of mime types keyed by their file extension regex. |
| 85 | */ |
| 86 | function wpcomsh_allow_file_uploads_with_invalid_mime_types( $file_data, $file, $filename, $mimes ) { |
| 87 | // Remove itself to avoid potential infinite loops |
| 88 | remove_filter( 'wp_check_filetype_and_ext', 'wpcomsh_allow_file_uploads_with_invalid_mime_types', 1000 ); |
| 89 | if ( ! file_exists( $file ) ) { |
| 90 | return $file_data; |
| 91 | } |
| 92 | |
| 93 | // If wp_check_filetype_and_ext already allows it or if the file does not, |
| 94 | // exist, don't bother doing the checks |
| 95 | if ( ! empty( $file_data['type'] ) ) { |
| 96 | return $file_data; |
| 97 | } |
| 98 | |
| 99 | // Try to get the file type with the extension based check, bail if it fails |
| 100 | $file_type = wp_check_filetype( $filename, $mimes ); |
| 101 | if ( empty( $file_type['type'] ) ) { |
| 102 | return $file_data; |
| 103 | } |
| 104 | |
| 105 | $finfo = finfo_open( FILEINFO_MIME_TYPE ); |
| 106 | $real_mime = finfo_file( $finfo, $file ); |
| 107 | // todo: remove when we are PHP 8.1+, as finfo_close() is noop in 8.1+ and deprecated in PHP 8.5+ |
| 108 | if ( PHP_VERSION_ID < 80100 ) { |
| 109 | finfo_close( $finfo ); // phpcs:ignore PHPCompatibility.FunctionUse.RemovedFunctions.finfo_closeDeprecated |
| 110 | } |
| 111 | |
| 112 | if ( empty( $real_mime ) ) { |
| 113 | return $file_data; |
| 114 | } |
| 115 | |
| 116 | $allowed = array(); |
| 117 | switch ( strtolower( $file_type['ext'] ) ) { |
| 118 | case 'doc': |
| 119 | case 'docm': |
| 120 | case 'docx': |
| 121 | $allowed[] = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'; |
| 122 | $allowed[] = 'application/vnd.openxmlformats-officedocument.wordprocessingml'; |
| 123 | $allowed[] = $file_type['type']; |
| 124 | $allowed[] = 'application/cdfv2'; |
| 125 | break; |
| 126 | case 'pot': |
| 127 | case 'pps': |
| 128 | case 'ppt': |
| 129 | case 'ppsm': |
| 130 | case 'ppsx': |
| 131 | case 'pptm': |
| 132 | case 'pptx': |
| 133 | $allowed[] = 'application/vnd.openxmlformats-officedocument.presentationml.presentation'; |
| 134 | $allowed[] = 'application/vnd.openxmlformats-officedocument.presentationml.slideshow'; |
| 135 | $allowed[] = $file_type['type']; |
| 136 | $allowed[] = 'application/cdfv2'; |
| 137 | break; |
| 138 | case 'xla': |
| 139 | case 'xls': |
| 140 | case 'xlt': |
| 141 | case 'xlw': |
| 142 | case 'xslb': |
| 143 | case 'xlsm': |
| 144 | case 'xlsx': |
| 145 | $allowed[] = 'application/vnd.openxmlformats-officedocument.spreadsheetml'; |
| 146 | $allowed[] = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'; |
| 147 | $allowed[] = $file_type['type']; |
| 148 | $allowed[] = 'application/cdfv2'; |
| 149 | break; |
| 150 | case 'odt': |
| 151 | $allowed[] = 'application/vnd.oasis.opendocument.presentation'; |
| 152 | $allowed[] = $file_type['type']; |
| 153 | $allowed[] = 'application/cdfv2'; |
| 154 | break; |
| 155 | } |
| 156 | |
| 157 | // Duplicate the mime types as a work around for https://bugs.php.net/bug.php?id=78028 |
| 158 | $_allowed = array_map( |
| 159 | function ( $item ) { |
| 160 | return $item . $item; |
| 161 | }, |
| 162 | $allowed |
| 163 | ); |
| 164 | if ( in_array( strtolower( $real_mime ), $allowed, true ) || in_array( strtolower( $real_mime ), $_allowed, true ) ) { |
| 165 | $file_data['type'] = $file_type['type']; |
| 166 | $file_data['ext'] = $file_type['ext']; |
| 167 | } |
| 168 | |
| 169 | return $file_data; |
| 170 | } |
| 171 | |
| 172 | add_filter( 'wp_check_filetype_and_ext', 'wpcomsh_allow_file_uploads_with_invalid_mime_types', 1000, 4 ); |