isFileTypeSupported($file)) { // throw new Exception('File type not supported'); // } // if ($file['size'] > $this->getFileUploadLimit()) { // throw new Exception('File size is too large'); // } // } private function getFileUploadLimit() { // Logic for calculating file upload limit as in your original code return min( wp_convert_hr_to_bytes(ini_get('upload_max_filesize')), wp_convert_hr_to_bytes(ini_get('post_max_size')), wp_max_upload_size() ); } /** * Delete a local attachment only when its stored path belongs to Fluent Boards. * * @param mixed $attachment * @param int|null $boardId * @return bool */ public function deleteAttachmentFile($attachment, $boardId = null) { if ( !$attachment || $attachment->attachment_type === 'url' || (!empty($attachment->driver) && $attachment->driver !== 'local') || empty($attachment->file_path) ) { return false; } $storedFilename = rawurldecode((string) $attachment->file_path); $isBareFilename = $storedFilename !== '' && strpos($storedFilename, '/') === false && strpos($storedFilename, '\\') === false; $filePath = FileSystem::resolveLocalAttachmentPath($attachment->file_path, $boardId); if (!$filePath) { return false; } // Legacy filenames need the board-qualified URL to distinguish same-named files across boards. if ($isBareFilename) { if ( empty($attachment->full_url) || Attachment::where('full_url', $attachment->full_url)->exists() ) { return false; } } elseif (Attachment::where('file_path', $attachment->file_path)->exists()) { return false; } return (bool) wp_delete_file($filePath); } /** * Summary of isFileTypeSupported checking file type it will allow only file which is readable by browser * @param mixed $file * TODO: Refactorable: This can be in a Helper class. and we may pass it to frontend via wp_localize_script appvars * so that we can check similarly for better experience. * @return bool */ public function isFileTypeSupported($file) { // Define supported file types that are generally allowed by user $allowedMimeTypes = get_allowed_mime_types(); // Check if the file type is supported return in_array(strtolower($file['type']), $allowedMimeTypes); } /** * @throws Exception */ public function handleMediaFileUpload($data) { // Check if file was uploaded // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verification handled by REST API/controller layer if (!isset($_FILES['file']['tmp_name']) || !isset($_FILES['file']['name'])) { throw new Exception(esc_html__('No file was uploaded. Please try again.', 'fluent-boards')); } // Sanitize filename from request for validation // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verification handled by REST API/controller layer $filename = sanitize_file_name(wp_unslash($_FILES['file']['name'])); // Validate and sanitize tmp_name before use // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verification handled by REST API/controller layer $tmp_name = sanitize_text_field(wp_unslash($_FILES['file']['tmp_name'])); if (empty($tmp_name) || !file_exists($tmp_name) || !is_uploaded_file($tmp_name)) { throw new Exception(esc_html__('Invalid upload. Please try again.', 'fluent-boards')); } // Check if the uploaded file is an image $wp_filetype = wp_check_filetype_and_ext($tmp_name, $filename); if ( ! wp_match_mime_types( 'image', $wp_filetype['type'] ) ) { throw new Exception(esc_html__('The uploaded file is not a valid image. Please try again.', 'fluent-boards')); } require_once(ABSPATH . 'wp-admin/includes/image.php'); require_once( ABSPATH . 'wp-admin/includes/file.php' ); require_once( ABSPATH . 'wp-admin/includes/media.php' ); $attachment_id = media_handle_upload( 'file', 0, [] ); $attachment = wp_prepare_attachment_for_js( $attachment_id); if(!$attachment) { throw new Exception(esc_html__('The uploaded file is not a valid image. Please try again.', 'fluent-boards')); } else { return $attachment; } } }