PluginProbe
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder / 2.21.4
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder v2.21.4
V-3.3.0 3.2.2 3.2.1 3.2.0 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 V3.0.3 V3.0.2 -3.0.1 V_3.0.0 1.1.1 1.1.8 1.2 1.3 1.4 1.4.18 1.5.2 1.9 2.0 2.10.0 2.10.1 2.10.2 All 137 releases
← All changes | includes/Core/Util/FileHandler.php +466 -45 2.02.21.4 View file →
@@ -1,12 +1,16 @@
1 1 <?php
2 2
3 3 namespace BitCode\BitForm\Core\Util;
4 4
5 +use BitCode\BitForm\Admin\Form\Helpers;
5 6 use BitCode\BitForm\Core\Form\FormManager;
7 +use BitCode\BitForm\enshrined\svgSanitize\Sanitizer;
6 8
7 -final class FileHandler {
8 - public function rmrf($dir) {
9 +final class FileHandler
10 +{
11 + public function rmrf($dir)
12 + {
9 13 if (is_dir($dir)) {
10 14 $objects = scandir($dir);
11 15 foreach ($objects as $object) {
12 16 if ('.' !== $object && '..' !== $object) {
@@ -12,19 +16,20 @@
12 16 if ('.' !== $object && '..' !== $object) {
13 17 if (is_dir($dir . DIRECTORY_SEPARATOR . $object) && !is_link($dir . DIRECTORY_SEPARATOR . $object)) {
14 18 $this->rmrf($dir . DIRECTORY_SEPARATOR . $object);
15 19 } else {
16 - unlink($dir . DIRECTORY_SEPARATOR . $object);
20 + wp_delete_file($dir . DIRECTORY_SEPARATOR . $object);
17 21 }
18 22 }
19 23 }
20 24 rmdir($dir);
21 25 } else {
22 - unlink($dir);
26 + wp_delete_file($dir);
23 27 }
24 28 }
25 29
26 - public function cpyr($source, $destination) {
30 + public function cpyr($source, $destination)
31 + {
27 32 if (is_dir($source)) {
28 33 mkdir($destination);
29 34 // chmod($destination, 0744);
30 35 $objects = scandir($source);
@@ -33,9 +38,9 @@
33 38 if (is_dir($source . DIRECTORY_SEPARATOR . $object) && !is_link($source . DIRECTORY_SEPARATOR . $object)) {
34 39 cpyr($source . DIRECTORY_SEPARATOR . $object, $destination . DIRECTORY_SEPARATOR . $object);
35 40 } elseif (is_file($source . DIRECTORY_SEPARATOR . $object)) {
36 41 copy($source . DIRECTORY_SEPARATOR . $object, $destination . DIRECTORY_SEPARATOR . $object);
37 - // chmod($destination. DIRECTORY_SEPARATOR .$object, 0644);
42 + // chmod($destination. DIRECTORY_SEPARATOR .$object, 0644);
38 43 } else {
39 44 symlink($source . DIRECTORY_SEPARATOR . $object, $destination . DIRECTORY_SEPARATOR . $object);
40 45 }
41 46 }
@@ -44,12 +49,13 @@
44 49 copy($source, $destination);
45 50 }
46 51 }
47 52
48 - public function moveUploadedFiles($file_details, $form_id, $entry_id) {
53 + public function moveUploadedFiles($file_details, $form_id, $entry_id)
54 + {
49 55 $file_upoalded = [];
50 - $_upload_dir = BITFORMS_UPLOAD_DIR . DIRECTORY_SEPARATOR . $form_id . DIRECTORY_SEPARATOR . $entry_id;
51 - wp_mkdir_p($_upload_dir);
56 + $_upload_dir = self::getEntriesFileUploadDir($form_id, $entry_id);
57 + $this::createIndexFile($_upload_dir);
52 58 if (is_array($file_details['name'])) {
53 59 foreach ($file_details['name'] as $key => $value) {
54 60 //check accepted filetype in_array($file_details['name'][$key], $supported_files) else \
55 61 if (!empty($value)) {
@@ -90,16 +96,18 @@
90 96 }
91 97 return $file_upoalded;
92 98 }
93 99
94 - public function deleteFiles($form_id, $entry_id, $files) {
95 - $_upload_dir = BITFORMS_UPLOAD_DIR . DIRECTORY_SEPARATOR . $form_id . DIRECTORY_SEPARATOR . $entry_id;
100 + public function deleteFiles($form_id, $entry_id, $files)
101 + {
102 + $_upload_dir = self::getEntriesFileUploadDir($form_id, $entry_id);
96 103 foreach ($files as $name) {
97 - unlink($_upload_dir . DIRECTORY_SEPARATOR . $name);
104 + wp_delete_file($_upload_dir . DIRECTORY_SEPARATOR . $name);
98 105 }
99 106 }
100 107
101 - public static function getFileUploadError($code) {
108 + public static function getFileUploadError($code)
109 + {
102 110 $errors = [
103 111 0 => __('Unknown upload error', 'bit-form'),
104 112 1 => __('The uploaded file exceeds the upload_max_filesize directive in php.ini.', 'bit-form'),
105 113 2 => __('The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.', 'bit-form'),
@@ -111,9 +119,10 @@
111 119 ];
112 120 return $errors[$code];
113 121 }
114 122
115 - public static function fileCopy($tmpdir, $destinationDir, $file) {
123 + public static function fileCopy($tmpdir, $destinationDir, $file)
124 + {
116 125 $tmpFile = $tmpdir . DIRECTORY_SEPARATOR . $file;
117 126 $newFile = $destinationDir . DIRECTORY_SEPARATOR . $file;
118 127 if (file_exists($tmpFile)) {
119 128 copy($tmpFile, $newFile);
@@ -119,15 +128,14 @@
119 128 copy($tmpFile, $newFile);
120 129 }
121 130 }
122 131
123 - public static function tempDirToUploadDir($submitted_data, $fields, $formId, $entryID) {
132 + public static function tempDirToUploadDir($submitted_data, $fields, $formId, $entryID)
133 + {
124 134 $upload_dir = wp_upload_dir();
125 135 $tempDir = $upload_dir['basedir'] . '/bitforms/temp';
126 - $destinationDir = BITFORMS_UPLOAD_DIR . DIRECTORY_SEPARATOR . $formId . DIRECTORY_SEPARATOR . $entryID . DIRECTORY_SEPARATOR;
127 - if (!is_dir($destinationDir)) {
128 - mkdir($destinationDir);
129 - }
136 + $destinationDir = self::getEntriesFileUploadDir($formId, $entryID) . DIRECTORY_SEPARATOR;
137 + self::createIndexFile($destinationDir);
130 138
131 139 foreach ($submitted_data as $key => $data) {
132 140 if (isset($fields[$key]) && 'advanced-file-up' === $fields[$key]['type']) {
133 141 $files = $data;
@@ -151,9 +159,10 @@
151 159
152 160 return $submitted_data;
153 161 }
154 162
155 - private function getByteSizeByUnit($sizeString) {
163 + private function getByteSizeByUnit($sizeString)
164 + {
156 165 // split 2MB into 2 and MB
157 166 $size = preg_replace('/[^0-9\.]/', '', $sizeString);
158 167 $unit = preg_replace('/[^a-zA-Z]/', '', $sizeString);
159 168 $unit = strtolower($unit);
@@ -167,14 +176,15 @@
167 176 return $size;
168 177 }
169 178 }
170 179
171 - public function validation($field_key, $file_details, $form_id) {
180 + public function validation($field_key, $file_details, $form_id)
181 + {
172 182 if (!function_exists('wp_check_filetype_and_ext')) {
173 183 require_once ABSPATH . 'wp-admin/includes/file.php';
174 184 }
175 185
176 - $formManager = new FormManager($form_id);
186 + $formManager = FormManager::getInstance($form_id);
177 187 $form_contents = $formManager->getFormContent();
178 188 $field_content_details = $form_contents->fields;
179 189 $fieldDetail = $field_content_details->{$field_key};
180 190 $fieldType = $fieldDetail->typ;
@@ -179,8 +189,9 @@
179 189 $fieldDetail = $field_content_details->{$field_key};
180 190 $fieldType = $fieldDetail->typ;
181 191 $maxSizeDetails = [];
182 192 $allowFileTypes = [];
193 + $maxSize = null;
183 194 if ('file-up' === $fieldType) {
184 195 $allowFileTypes = !empty($fieldDetail->config->allowedFileType) ? $fieldDetail->config->allowedFileType : [];
185 196 if (!empty($fieldDetail->config->allowMaxSize)) {
186 197 if (!empty($fieldDetail->config->maxSize)) {
@@ -206,20 +217,44 @@
206 217 }
207 218 if (!empty($maxSizeDetails['maxSize'])) {
208 219 $maxSize = $this->getByteSizeByUnit($maxSizeDetails['maxSize']);
209 220 }
221 + $maxTotalFileSize = null;
210 222 if (!empty($maxSizeDetails['maxTotalFileSize'])) {
211 223 $maxTotalFileSize = $this->getByteSizeByUnit($maxSizeDetails['maxTotalFileSize']);
212 224 }
213 225
226 + if ($formManager->isRepeatedField($field_key)) {
227 + foreach ($file_details['name'] as $rowIndex => $file) {
228 + if (!empty($file)) {
229 + $fileDetails = [
230 + 'name' => $file,
231 + 'type' => $file_details['type'][$rowIndex],
232 + 'tmp_name' => $file_details['tmp_name'][$rowIndex],
233 + 'error' => $file_details['error'][$rowIndex],
234 + 'size' => $file_details['size'][$rowIndex],
235 + ];
236 + $validateState = $this->validateFileInfo($fieldType, $fileDetails, $allowFileTypes, $maxSize, $maxTotalFileSize);
237 + if (!empty($validateState) && !empty($validateState['message'])) {
238 + return $validateState;
239 + }
240 + }
241 + }
242 + } else {
243 + return $this->validateFileInfo($fieldType, $file_details, $allowFileTypes, $maxSize, $maxTotalFileSize);
244 + }
245 + return [];
246 + }
247 +
248 + private function validateFileInfo($fieldType, $file_details, $allowFileTypes, $maxSize, $maxTotalFileSize)
249 + {
214 250 $errorMessage = [
215 251 'message' => '',
216 252 'error_type'=> '',
217 253 ];
218 -
219 254 if (is_array($file_details['name'])) {
220 255 $totalSize = 0;
221 - foreach ($file_details['name'] as $key => $file) {
256 + foreach ($file_details['name'] as $key => $file) {
222 257 if (!empty($file)) {
223 258 $fileInfo = [
224 259 'name' => $file,
225 260 'type' => $file_details['type'][$key],
@@ -233,9 +268,9 @@
233 268 return $validateState;
234 269 }
235 270 }
236 271 }
237 - if (!is_null($maxTotalFileSize) && $totalSize > $maxTotalFileSize) {
272 + if (isset($maxTotalFileSize) && !is_null($maxTotalFileSize) && $totalSize > $maxTotalFileSize) {
238 273 $errorMessage['message'] = __('Total File size is too large', 'bit-form');
239 274 $errorMessage['error_type'] = 'file_size_error';
240 275 return $errorMessage;
241 276 }
@@ -248,31 +283,417 @@
248 283
249 284 return $errorMessage;
250 285 }
251 286
252 - private function validateSingleFile($fieldType, $file, $allowTypes, $maxSize) {
253 - $fileName = sanitize_file_name($file['name']);
254 - if (!empty($fileName)) {
255 - $fileSize = $file['size'];
256 - if (!empty($maxSize) && $fileSize > $maxSize) {
257 - return [
258 - 'message' => __('File size is too large', 'bit-form'),
259 - 'error_type'=> 'file_size_error',
260 - ];
287 + private function validateSingleFile($fieldType, &$file, $allowTypes, $maxSize = null)
288 + {
289 + // 0) Basic sanity & transport integrity
290 + if (!is_array($file) || empty($file['tmp_name'])) {
291 + // return ['message' => __('No file uploaded.', 'bit-form'), 'error_type' => 'file_missing'];
292 + return null;
293 + }
294 + if (!isset($file['error']) || UPLOAD_ERR_OK !== $file['error']) {
295 + return ['message' => __('Upload failed', 'bit-form'), 'error_type' => 'file_upload_error'];
296 + }
297 + if (!is_uploaded_file($file['tmp_name'])) {
298 + return ['message' => __('Untrusted upload source', 'bit-form'), 'error_type' => 'file_upload_error'];
299 + }
300 + if (!is_file($file['tmp_name']) || !is_readable($file['tmp_name'])) {
301 + return ['message' => __('Temporary file not accessible', 'bit-form'), 'error_type' => 'file_upload_error'];
302 + }
303 +
304 + $fileName = sanitize_file_name((string)($file['name'] ?? ''));
305 + if ('' === $fileName) {
306 + return ['message' => __('Empty filename', 'bit-form'), 'error_type' => 'file_type_error'];
307 + }
308 +
309 + // 1) Enforce max size (header + actual)
310 + $onDiskSize = @filesize($file['tmp_name']);
311 + if (false === $onDiskSize) {
312 + return ['message' => __('Cannot read file size', 'bit-form'), 'error_type' => 'file_upload_error'];
313 + }
314 + if (!empty($maxSize) && $onDiskSize > $maxSize) {
315 + return ['message' => __('File size is too large', 'bit-form'), 'error_type' => 'file_size_error'];
316 + }
317 +
318 + // 2) Determine ext + MIME using WP + finfo
319 + $wpCheck = wp_check_filetype_and_ext($file['tmp_name'], $fileName); // ['ext'=>'jpg','type'=>'image/jpeg']
320 + $fileExtension = strtolower((string)(empty($wpCheck['ext']) ? pathinfo($fileName, PATHINFO_EXTENSION) : $wpCheck['ext']));
321 + $wpExt = strtolower((string)(empty($wpCheck['ext']) ? $fileExtension : $wpCheck['ext']));
322 + $wpType = strtolower((string)($wpCheck['type'] ?? ''));
323 + $fi = function_exists('finfo_open') ? @finfo_open(FILEINFO_MIME_TYPE) : false;
324 + $detectedMime = $fi ? @finfo_file($fi, $file['tmp_name']) : false;
325 + if ($fi) {
326 + @finfo_close($fi);
327 + }
328 + if (!$detectedMime && function_exists('mime_content_type')) {
329 + $detectedMime = @mime_content_type($file['tmp_name']);
330 + }
331 + if (!$detectedMime) {
332 + $detectedMime = '' !== $wpType ? $wpType : 'application/octet-stream';
333 + }
334 + $detectedMime = strtolower(trim($detectedMime));
335 +
336 + // Hard-block risky types regardless
337 + // 3) Block obvious executable types regardless of allow list
338 + $disallowedMimes = apply_filters('bitform_filter_upload_disallowed_mimes', [
339 + 'application/x-php', 'text/x-php', 'application/x-msdownload', 'application/x-msdos-program',
340 + 'application/x-sh', 'application/x-csh', 'text/x-shellscript', 'application/java-archive'
341 + ]);
342 + $denyExt = apply_filters('bitform_filter_upload_denied_extensions', ['php', 'phtml', 'phar', 'htaccess', 'html', 'js', 'exe', 'sh', 'bat', 'cmd']);
343 + if (in_array($detectedMime, $disallowedMimes, true) || in_array($fileExtension, $denyExt, true)) {
344 + return ['message' => __('This file type is not allowed', 'bit-form'), 'error_type' => 'file_type_error'];
345 + }
346 +
347 + // 4) Normalize allowlist: support both extensions (.jpg or jpg) and MIME types
348 + // --- ALLOWLIST NORMALIZATION (extensions + MIME) ---
349 + $normalizedAllow = array_values(array_unique(array_map(static function ($t) {
350 + return strtolower(trim((string)$t));
351 + }, (array)$allowTypes)));
352 +
353 + $allowExts = [];
354 + $allowMimes = [];
355 + foreach ($normalizedAllow as $t) {
356 + if ('' === $t) {
357 + continue;
261 358 }
359 + if (false !== strpos($t, '/')) {
360 + // looks like a MIME
361 + $allowMimes[] = $t;
362 + } else {
363 + // extension: may include leading dot; normalize without dot
364 + $allowExts[] = ltrim($t, '.');
365 + }
366 + }
262 367
263 - $fileExtension = pathinfo($fileName, PATHINFO_EXTENSION);
264 - $fileExtAllowedByWp = wp_check_filetype_and_ext($file['tmp_name'], $fileName);
265 - $isAllowedFileType = in_array('.' . $fileExtension, $allowTypes);
266 - if ('advanced-file-up' === $fieldType && !empty($allowTypes)) {
267 - $fileMimeType = mime_content_type($file['tmp_name']);
268 - $isAllowedFileType = in_array($fileMimeType, $allowTypes);
368 + $allowExts = array_values(array_unique($allowExts));
369 + $allowMimes = array_values(array_unique($allowMimes));
370 +
371 + $hasAllowlist = (!empty($allowExts) || !empty($allowMimes));
372 + $extMatch = in_array($fileExtension, $allowExts, true);
373 + $mimeMatch = in_array($detectedMime, $allowMimes, true);
374 +
375 + // 5) Require BOTH a legit WP mapping AND a match to the allowlist
376 + $wpOk = ('' !== $wpExt && '' !== $wpType);
377 +
378 + if ($hasAllowlist) {
379 + if (!($extMatch || $mimeMatch)) {
380 + return ['message' => __('File type is not allowed', 'bit-form'), 'error_type' => 'file_type_error'];
269 381 }
270 - if ((!empty($allowTypes) && !$isAllowedFileType) || (empty($allowTypes) && empty($fileExtAllowedByWp['ext']))) {
271 - return [
272 - 'message' => __(($fileExtension ? ".{$fileExtension}" : 'empty') . ' file extension is not allowed', 'bit-form'),
273 - 'error_type'=> 'file_type_error',
274 - ];
382 + } else {
383 + if (!$wpOk) {
384 + return ['message' => __('File type is not allowed', 'bit-form'), 'error_type' => 'file_type_error'];
275 385 }
386 + }
387 +
388 + // 5) Special SVG handling (by MIME, not just extension)
389 + if ('svg' === $fileExtension || 'image/svg+xml' === $detectedMime || 'image/svg+xml' === $wpType) {
390 + if ('image/svg+xml' !== $detectedMime) {
391 + return ['message' => __('Invalid SVG', 'bit-form'), 'error_type' => 'file_type_error'];
392 + }
393 +
394 + $dirty = file_get_contents($file['tmp_name']);
395 + $svg_sanitizer = new Sanitizer();
396 + $clean = $svg_sanitizer->sanitize($dirty);
397 + if (false === $clean) {
398 + return ['message' => __('SVG file is not valid', 'bit-form'), 'error_type' => 'file_type_error'];
399 + }
400 + file_put_contents($file['tmp_name'], $clean, LOCK_EX);
401 + // Re-check size post-sanitize
402 + if (!empty($maxSize) && filesize($file['tmp_name']) > $maxSize) {
403 + return ['message' => __('File size is too large after sanitation', 'bit-form'), 'error_type' => 'file_size_error'];
404 + }
405 + }
406 +
407 + // --- Allow developer to make a final decision override (optional) ---
408 + $final = apply_filters('bit_form_upload_allow_file', true, [
409 + 'file_name' => $fileName,
410 + 'extension' => $fileExtension,
411 + 'detected_mime' => $detectedMime,
412 + 'wp_ext' => $wpExt,
413 + 'wp_type' => $wpType,
414 + 'allow_exts' => $allowExts,
415 + 'allow_mimes' => $allowMimes,
416 + 'has_allowlist' => $hasAllowlist,
417 + ]);
418 + if (true !== $final) {
419 + // If a dev returns a WP_Error, you could extract message/type; here we just block.
420 + return ['message' => __('File not allowed by policy', 'bit-form'), 'error_type' => 'file_policy_block'];
421 + }
422 + return null; // success
423 + }
424 +
425 + public static function deleteIsFileExists($path)
426 + {
427 + if (file_exists($path)) {
428 + wp_delete_file($path);
429 + }
430 + }
431 +
432 + public static function getEntriesFileUploadDir($form_id, $entry_id)
433 + {
434 + $uploadDir = rtrim(BITFORMS_UPLOAD_DIR, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $form_id . DIRECTORY_SEPARATOR;
435 + $previousEntryDirectory = $uploadDir . $entry_id;
436 + if (is_dir($previousEntryDirectory)) {
437 + return $previousEntryDirectory;
438 + }
439 + $encrypted_directory = Helpers::getEncryptedEntryId($entry_id);
440 + return $uploadDir . $encrypted_directory;
441 + }
442 +
443 + private static function replaceDocumentRoot($path)
444 + {
445 + $relativePath = str_replace(ABSPATH, '', $path); // Remove absolute server path
446 + return site_url($relativePath); // Prepend with domain
447 + }
448 +
449 + public static function getEntriesFileUploadURL($form_id, $entry_id)
450 + {
451 + $documentRoot = self::getEntriesFileUploadDir($form_id, $entry_id);
452 + $url = self::replaceDocumentRoot($documentRoot);
453 + return $url;
454 + }
455 +
456 + public static function createIndexFile($directory)
457 + {
458 + if (wp_mkdir_p($directory)) {
459 + $indexFilePath = rtrim($directory, '/') . '/index.php';
460 + if (!file_exists($indexFilePath)) {
461 + try {
462 + if (false === file_put_contents($indexFilePath, "<?php\n// No direct access allowed.")) {
463 + throw new \Exception("Failed to create index.php in $directory");
464 + }
465 + } catch (\Exception $e) {
466 + Log::debug_log('File creation Failed:' . $e->getMessage()); // Log the error for debugging
467 + }
468 + }
469 + }
470 + return false;
471 + }
472 +
473 + public static function processRepeaterAttachment($repeaterKey, $fileKey, $fieldValue, $basePath, &$attachments)
474 + {
475 + if (!isset($fieldValue[$repeaterKey]) || !is_array($fieldValue[$repeaterKey])) {
476 + return;
477 + }
478 +
479 + foreach ($fieldValue[$repeaterKey] as $repeaterRow) {
480 + if (!isset($repeaterRow[$fileKey]) || empty($repeaterRow[$fileKey])) {
481 + continue;
482 + }
483 +
484 + $fileValue = $repeaterRow[$fileKey];
485 + self::addAttachmentFiles($fileValue, $basePath, $attachments);
486 + }
487 + }
488 +
489 + public static function processRegularAttachment($fileKey, $fieldValue, $basePath, &$attachments)
490 + {
491 + if (!isset($fieldValue[$fileKey]) || empty($fieldValue[$fileKey])) {
492 + return;
493 + }
494 +
495 + $fileValue = $fieldValue[$fileKey];
496 + self::addAttachmentFiles($fileValue, $basePath, $attachments);
497 + }
498 +
499 + private static function addAttachmentFiles($fileValue, $basePath, &$attachments)
500 + {
501 + if (is_array($fileValue)) {
502 + foreach ($fileValue as $singleFile) {
503 + $filePath = $basePath . $singleFile;
504 + if (is_readable($filePath)) {
505 + $attachments[] = $filePath;
506 + }
507 + }
508 + } else {
509 + $filePath = $basePath . $fileValue;
510 + if (is_readable($filePath)) {
511 + $attachments[] = $filePath;
512 + }
513 + }
514 + }
515 +
516 + /**
517 + * Return file type by checking with mime type
518 + * @param string $mime
519 + * @return string
520 + */
521 + public static function getFileTypeByMime(string $mime)
522 + {
523 + $mime = strtolower($mime);
524 +
525 + if (preg_match('/^image\//', $mime)) {
526 + return 'image';
527 + }
528 +
529 + $compressed = [
530 + 'application/zip',
531 + 'application/x-rar-compressed',
532 + 'application/x-7z-compressed',
533 + 'application/gzip',
534 + 'application/x-tar',
535 + 'application/x-gtar',
536 + 'application/x-bzip2',
537 + 'application/x-archive',
538 + 'application/vnd.debian.binary-package',
539 + ];
540 + if (in_array($mime, $compressed, true)) {
541 + return 'compressed';
542 + }
543 +
544 + $presentation = [
545 + 'application/vnd.ms-powerpoint',
546 + 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
547 + 'application/vnd.oasis.opendocument.presentation',
548 + 'application/vnd.apple.keynote',
549 + ];
550 + if (in_array($mime, $presentation, true)) {
551 + return 'presentation';
552 + }
553 +
554 + $document = [
555 + 'application/pdf',
556 + 'application/msword',
557 + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
558 + 'application/rtf',
559 + 'text/plain',
560 + 'application/vnd.oasis.opendocument.text',
561 + 'application/x-tex',
562 + 'text/rtf',
563 + ];
564 + if (in_array($mime, $document, true)) {
565 + return 'document';
566 + }
567 +
568 + $data = [
569 + 'text/csv',
570 + 'application/xml',
571 + 'text/xml',
572 + 'application/sql',
573 + 'application/vnd.ms-excel',
574 + 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
575 + 'application/x-sqlite3',
576 + 'application/octet-stream', // generic binary (could be db files)
577 + ];
578 + if (in_array($mime, $data, true)) {
579 + return 'data';
580 + }
581 +
582 + if (preg_match('/^audio\//', $mime)) {
583 + return 'audio';
584 + }
585 +
586 + if (preg_match('/^video\//', $mime)) {
587 + return 'video';
588 + }
589 +
590 + return 'other';
591 + }
592 +
593 + /**
594 + * Return file type by checking with extension
595 + * @param string $extension
596 + * @return string
597 + */
598 + public static function getFileTypeByExtension($extension)
599 + {
600 + switch (strtolower($extension)) {
601 + case 'xbm':
602 + case 'tif':
603 + case 'pjp':
604 + case 'pjpeg':
605 + case 'svgz':
606 + case 'jpg':
607 + case 'jpeg':
608 + case 'ico':
609 + case 'tiff':
610 + case 'gif':
611 + case 'svg':
612 + case 'bmp':
613 + case 'png':
614 + case 'jfif':
615 + case 'webp':
616 + return 'image';
617 +
618 + case '7z':
619 + case 'arj':
620 + case 'deb':
621 + case 'pkg':
622 + case 'rar':
623 + case 'rpm':
624 + case 'gz':
625 + case 'z':
626 + case 'zip':
627 + return 'compressed';
628 +
629 + case 'key':
630 + case 'odp':
631 + case 'pps':
632 + case 'ppt':
633 + case 'pptx':
634 + return 'presentation';
635 +
636 + case '_rf_':
637 + case 'doc':
638 + case 'docx':
639 + case 'odt':
640 + case 'pdf':
641 + case 'rtf':
642 + case 'tex':
643 + case 'txt':
644 + case 'wks':
645 + case 'wps':
646 + case 'wpd':
647 + return 'document';
648 +
649 + case 'csv':
650 + case 'dat':
651 + case 'db':
652 + case 'dbf':
653 + case 'log':
654 + case 'mdb':
655 + case 'sav':
656 + case 'sql':
657 + case 'tar':
658 + case 'sqlite':
659 + case 'xml':
660 + return 'data';
661 +
662 + case 'opus':
663 + case 'flac':
664 + case 'webm':
665 + case 'weba':
666 + case 'wav':
667 + case 'ogg':
668 + case 'm4a':
669 + case 'mp3':
670 + case 'oga':
671 + case 'mid':
672 + case 'amr':
673 + case 'aiff':
674 + case 'wma':
675 + case 'au':
676 + case 'acc':
677 + case 'wpl':
678 + return 'audio';
679 +
680 + case 'ogm':
681 + case 'wmv':
682 + case 'mpg':
683 + case 'ogv':
684 + case 'mov':
685 + case 'asx':
686 + case 'mpeg':
687 + case 'mp4':
688 + case 'm4v':
689 + case 'avi':
690 + case '3gp':
691 + case 'flv':
692 + case 'mkv':
693 + case 'swf':
694 + return 'video';
695 + default:
696 + return 'other';
276 697 }
277 698 }
278 699 }