PluginProbe
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration / 2.0.12
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration v2.0.12
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 / Services / UploadService.php

UploadService.php in FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration 2.0.12, at app/Services/UploadService.php

112 lines 3.7 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\Services;
4
5
6 use FluentBoards\App\Services\Libs\FileSystem;
7 use FluentBoards\Framework\Support\Arr;
8
9 class UploadService
10 {
11 const MAX_FILE_UPLOAD_BYTES = 104857600;
12
13 /**
14 * @throws \Exception
15 */
16 public static function handleFileUpload($file, $boardId, $taskId = null)
17 {
18 $uploadInfo = FileSystem::setSubDir('board_'.$boardId)->put($file);
19
20 if (!empty($uploadInfo) && is_array($uploadInfo)) {
21 return $uploadInfo;
22 }
23
24 return new \WP_Error('file_upload_error', __('File upload failed', 'fluent-boards'));
25 }
26
27 public function validateFile($file)
28 {
29 if (!$file) {
30 throw new \Exception(esc_html__('File is empty.', 'fluent-boards'));
31 }
32 if (!$this->isFileTypeSupported($file)) {
33 throw new \Exception(esc_html__('File type not supported', 'fluent-boards'));
34 }
35 if ($file['size_in_bytes'] > $this->getFileUploadLimit()) {
36 throw new \Exception(esc_html__('File size is too large', 'fluent-boards'));
37 }
38 }
39
40 public function getFileUploadLimit() {
41 return (int) apply_filters('fluent_boards/upload_file_size_limit', self::MAX_FILE_UPLOAD_BYTES);
42 }
43
44 public function isFileTypeSupported($file)
45 {
46 // Validate by extension against our allow-list. This is more reliable than the
47 // browser-provided mime, which is empty/inconsistent for types like .json and .md.
48 $extension = strtolower(pathinfo(Arr::get($file, 'name', ''), PATHINFO_EXTENSION));
49 if (!$extension) {
50 return false;
51 }
52
53 foreach (array_keys(self::getAllowedMimeMap()) as $extensionPattern) {
54 if (in_array($extension, explode('|', $extensionPattern), true)) {
55 return true;
56 }
57 }
58
59 return false;
60 }
61
62 /**
63 * Allow-list of upload types as an extension => mime map (WordPress defaults plus
64 * common developer/document formats). Shared by validateFile() and wp_handle_upload()
65 * so both agree. Executable/script types are intentionally excluded.
66 *
67 * @return array
68 */
69 public static function getAllowedMimeMap()
70 {
71 $extraMimes = [
72 'json' => 'application/json',
73 'md' => 'text/markdown',
74 'markdown' => 'text/markdown',
75 'csv' => 'text/csv',
76 'txt' => 'text/plain',
77 'log' => 'text/plain',
78 'xml' => 'text/xml',
79 'yaml|yml' => 'text/yaml',
80 'webp' => 'image/webp',
81 'avif' => 'image/avif',
82 'heic' => 'image/heic',
83 'zip' => 'application/zip',
84 'rar' => 'application/vnd.rar',
85 '7z' => 'application/x-7z-compressed',
86 'tar' => 'application/x-tar',
87 'gz|gzip' => 'application/gzip',
88 ];
89
90 $map = array_merge(get_allowed_mime_types(), $extraMimes);
91 $map = apply_filters('fluent_boards/upload_allowed_mimes', $map);
92
93 // Never allow executable or browser-active formats through plugin filters.
94 $blockedExtensions = [
95 'php', 'php3', 'php4', 'php5', 'php7', 'php8', 'phtml', 'phar',
96 'html', 'htm', 'shtml', 'xhtml', 'xht',
97 'js', 'mjs', 'svg', 'svgz', 'xml', 'xsl', 'xslt', 'swf', 'htaccess',
98 ];
99 $safeMap = [];
100
101 foreach ($map as $extensionPattern => $mimeType) {
102 $extensions = array_diff(explode('|', strtolower($extensionPattern)), $blockedExtensions);
103 if ($extensions) {
104 $safeMap[implode('|', $extensions)] = $mimeType;
105 }
106 }
107
108 return $safeMap;
109 }
110
111 }
112