PluginProbe
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration / trunk
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration vtrunk
2.0.15 2.0.12 2.0.10 2.0.4 2.0.1 2.0.0 1.95.3 1.95.2 1.95 1.91.6 trunk 1.11 1.12 1.13 1.20 1.21 1.22 1.23 1.30 1.31 1.32 1.35 1.40 1.41 1.45 All 41 releases
fluent-boards / app / Hooks / Handlers / FileHandler.php

FileHandler.php in FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration trunk, at app/Hooks/Handlers/FileHandler.php

138 lines 5.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentBoards\App\Hooks\Handlers;
4
5 use DateTimeImmutable;
6 use Exception;
7 use FluentBoards\App\Services\Libs\FileSystem;
8 use FluentBoards\App\Models\Attachment;
9 use function Sodium\add;
10
11 class FileHandler
12 {
13 // private function validateFile($file)
14 // {
15 // if (!$file) {
16 // throw new Exception('File is empty.');
17 // }
18 // if (!$this->isFileTypeSupported($file)) {
19 // throw new Exception('File type not supported');
20 // }
21 // if ($file['size'] > $this->getFileUploadLimit()) {
22 // throw new Exception('File size is too large');
23 // }
24 // }
25
26 private function getFileUploadLimit() {
27 // Logic for calculating file upload limit as in your original code
28 return min(
29 wp_convert_hr_to_bytes(ini_get('upload_max_filesize')),
30 wp_convert_hr_to_bytes(ini_get('post_max_size')),
31 wp_max_upload_size()
32 );
33 }
34
35 /**
36 * Delete a local attachment only when its stored path belongs to Fluent Boards.
37 *
38 * @param mixed $attachment
39 * @param int|null $boardId
40 * @return bool
41 */
42 public function deleteAttachmentFile($attachment, $boardId = null)
43 {
44 if (
45 !$attachment ||
46 $attachment->attachment_type === 'url' ||
47 (!empty($attachment->driver) && $attachment->driver !== 'local') ||
48 empty($attachment->file_path)
49 ) {
50 return false;
51 }
52
53 $storedFilename = rawurldecode((string) $attachment->file_path);
54 $isBareFilename = $storedFilename !== ''
55 && strpos($storedFilename, '/') === false
56 && strpos($storedFilename, '\\') === false;
57 $filePath = FileSystem::resolveLocalAttachmentPath($attachment->file_path, $boardId);
58
59 if (!$filePath) {
60 return false;
61 }
62
63 // Legacy filenames need the board-qualified URL to distinguish same-named files across boards.
64 if ($isBareFilename) {
65 if (
66 empty($attachment->full_url) ||
67 Attachment::where('full_url', $attachment->full_url)->exists()
68 ) {
69 return false;
70 }
71 } elseif (Attachment::where('file_path', $attachment->file_path)->exists()) {
72 return false;
73 }
74
75 return (bool) wp_delete_file($filePath);
76 }
77
78
79 /**
80 * Summary of isFileTypeSupported checking file type it will allow only file which is readable by browser
81 * @param mixed $file
82 * TODO: Refactorable: This can be in a Helper class. and we may pass it to frontend via wp_localize_script appvars
83 * so that we can check similarly for better experience.
84 * @return bool
85 */
86 public function isFileTypeSupported($file)
87 {
88 // Define supported file types that are generally allowed by user
89 $allowedMimeTypes = get_allowed_mime_types();
90
91 // Check if the file type is supported
92 return in_array(strtolower($file['type']), $allowedMimeTypes);
93 }
94
95 /**
96 * @throws Exception
97 */
98 public function handleMediaFileUpload($data)
99 {
100 // Check if file was uploaded
101 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verification handled by REST API/controller layer
102 if (!isset($_FILES['file']['tmp_name']) || !isset($_FILES['file']['name'])) {
103 throw new Exception(esc_html__('No file was uploaded. Please try again.', 'fluent-boards'));
104 }
105
106 // Sanitize filename from request for validation
107 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verification handled by REST API/controller layer
108 $filename = sanitize_file_name(wp_unslash($_FILES['file']['name']));
109
110 // Validate and sanitize tmp_name before use
111 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verification handled by REST API/controller layer
112 $tmp_name = sanitize_text_field(wp_unslash($_FILES['file']['tmp_name']));
113
114 if (empty($tmp_name) || !file_exists($tmp_name) || !is_uploaded_file($tmp_name)) {
115 throw new Exception(esc_html__('Invalid upload. Please try again.', 'fluent-boards'));
116 }
117
118 // Check if the uploaded file is an image
119 $wp_filetype = wp_check_filetype_and_ext($tmp_name, $filename);
120
121 if ( ! wp_match_mime_types( 'image', $wp_filetype['type'] ) ) {
122 throw new Exception(esc_html__('The uploaded file is not a valid image. Please try again.', 'fluent-boards'));
123 }
124 require_once(ABSPATH . 'wp-admin/includes/image.php');
125 require_once( ABSPATH . 'wp-admin/includes/file.php' );
126 require_once( ABSPATH . 'wp-admin/includes/media.php' );
127 $attachment_id = media_handle_upload( 'file', 0, [] );
128
129 $attachment = wp_prepare_attachment_for_js( $attachment_id);
130 if(!$attachment) {
131 throw new Exception(esc_html__('The uploaded file is not a valid image. Please try again.', 'fluent-boards'));
132 } else {
133 return $attachment;
134 }
135 }
136
137 }
138