diff --git a/post/user/file.php b/post/user/file.php index e1d9a006..68b2305c 100644 --- a/post/user/file.php +++ b/post/user/file.php @@ -7,66 +7,83 @@ defined('FROM_POST_HANDLER') || die("Direct file access is not allowed"); if (isset($_POST['upload_files'])) { - - enforceUserPermission('module_support', 2); - $client_id = intval($_POST['client_id']); - $folder_id = intval($_POST['folder_id']); + // Enforce required user permission + enforceUserPermission('module_support', 2); + + // Sanitize and initialize inputs + $client_id = intval($_POST['client_id']); + $folder_id = intval($_POST['folder_id']); $description = sanitizeInput($_POST['description']); + $client_dir = "uploads/clients/$client_id"; - if (!file_exists("uploads/clients/$client_id")) { - mkdir("uploads/clients/$client_id"); + // Create client directory if it doesn't exist + if (!is_dir($client_dir)) { + mkdir($client_dir, 0755, true); } - for ($i = 0; $i < count($_FILES['file']['name']); $i++) { - // Extract file details for this iteration + // Allowed file extensions list + $allowedExtensions = [ + 'jpg', 'jpeg', 'gif', 'png', 'webp', 'pdf', 'txt', 'md', 'doc', 'docx', + 'odt', 'csv', 'xls', 'xlsx', 'ods', 'pptx', 'odp', 'zip', 'tar', 'gz', + 'xml', 'msg', 'json', 'wav', 'mp3', 'ogg', 'mov', 'mp4', 'av1', 'ovpn', + 'cfg', 'ps1', 'vsdx', 'drawio', 'pfx', 'pages', 'numbers', 'unf', 'key' + ]; + + // Loop through each uploaded file + foreach ($_FILES['file']['name'] as $index => $originalName) { + + // Build a file array for this iteration $single_file = [ - 'name' => $_FILES['file']['name'][$i], - 'type' => $_FILES['file']['type'][$i], - 'tmp_name' => $_FILES['file']['tmp_name'][$i], - 'error' => $_FILES['file']['error'][$i], - 'size' => $_FILES['file']['size'][$i] + 'name' => $_FILES['file']['name'][$index], + 'type' => $_FILES['file']['type'][$index], + 'tmp_name' => $_FILES['file']['tmp_name'][$index], + 'error' => $_FILES['file']['error'][$index], + 'size' => $_FILES['file']['size'][$index] ]; - if ($file_reference_name = checkFileUpload($single_file, array('jpg', 'jpeg', 'gif', 'png', 'webp', 'pdf', 'txt', 'md', 'doc', 'docx', 'odt', 'csv', 'xls', 'xlsx', 'ods', 'pptx', 'odp', 'zip', 'tar', 'gz', 'xml', 'msg', 'json', 'wav', 'mp3', 'ogg', 'mov', 'mp4', 'av1', 'ovpn', 'cfg', 'ps1', 'vsdx', 'drawio', 'pfx', 'pages', 'numbers', 'unf', 'key'))) { + // Validate and get a safe file reference name + if ($file_reference_name = checkFileUpload($single_file, $allowedExtensions)) { - $file_tmp_path = $_FILES['file']['tmp_name'][$i]; + $file_tmp_path = $single_file['tmp_name']; + $file_name = sanitizeInput($originalName); + $extParts = explode('.', $file_name); + $file_extension = strtolower(end($extParts)); + $file_mime_type = sanitizeInput($single_file['type']); + $file_size = intval($single_file['size']); - $file_name = sanitizeInput($_FILES['file']['name'][$i]); - $extarr = explode('.', $_FILES['file']['name'][$i]); - $file_extension = sanitizeInput(strtolower(end($extarr))); + // Define destination path and move the uploaded file + $upload_file_dir = $client_dir . "/"; + $dest_path = $upload_file_dir . $file_reference_name; - // Extract the file mime type and size - $file_mime_type = sanitizeInput($single_file['type']); - $file_size = intval($single_file['size']); + if (!move_uploaded_file($file_tmp_path, $dest_path)) { + $_SESSION['alert_type'] = 'error'; + $_SESSION['alert_message'] = 'Error moving file to upload directory. Please ensure the directory is writable.'; + continue; // Skip processing this file + } - // directory in which the uploaded file will be moved - $upload_file_dir = "uploads/clients/$client_id/"; - $dest_path = $upload_file_dir . $file_reference_name; - - move_uploaded_file($file_tmp_path, $dest_path); - - // Extract .ext from reference file name to be used to store SHA256 hash + // Use the file reference (without extension) as the file hash $file_hash = strstr($file_reference_name, '.', true) ?: $file_reference_name; - mysqli_query($mysqli,"INSERT INTO files SET file_reference_name = '$file_reference_name', file_name = '$file_name', file_description = '$description', file_ext = '$file_extension', file_hash = '$file_hash', file_mime_type = '$file_mime_type', file_size = $file_size, file_created_by = $session_user_id, file_folder_id = $folder_id, file_client_id = $client_id"); - + // Insert file metadata into the database + $query = "INSERT INTO files SET + file_reference_name = '$file_reference_name', + file_name = '$file_name', + file_description = '$description', + file_ext = '$file_extension', + file_hash = '$file_hash', + file_mime_type = '$file_mime_type', + file_size = $file_size, + file_created_by = $session_user_id, + file_folder_id = $folder_id, + file_client_id = $client_id"; + mysqli_query($mysqli, $query); $file_id = mysqli_insert_id($mysqli); - // If the file is an image, create a thumbnail and an optimized preview image + // If the file is an image, create a thumbnail and an optimized preview if (in_array($file_extension, ['jpg', 'jpeg', 'png', 'gif', 'webp'])) { - // Thumbnail dimensions - $thumbnail_width = 200; - $thumbnail_height = 200; - // Optimized preview dimensions - $preview_max_width = 1200; - $preview_max_height = 1200; - - // Get original dimensions - list($orig_width, $orig_height) = getimagesize($dest_path); - - // Create image resource from the original file + // Create image resource based on file extension switch ($file_extension) { case 'jpg': case 'jpeg': @@ -81,21 +98,42 @@ if (isset($_POST['upload_files'])) { case 'webp': $src_img = imagecreatefromwebp($dest_path); break; + default: + $src_img = false; } if ($src_img) { - // ------------------------- - // CREATE THUMBNAIL - // ------------------------- + + // Fix image rotation for JPEG images using EXIF data + if (in_array($file_extension, ['jpg', 'jpeg']) && function_exists('exif_read_data')) { + $exif = @exif_read_data($dest_path); + if (!empty($exif['Orientation'])) { + switch ($exif['Orientation']) { + case 3: + $src_img = imagerotate($src_img, 180, 0); + break; + case 6: + $src_img = imagerotate($src_img, -90, 0); + break; + case 8: + $src_img = imagerotate($src_img, 90, 0); + break; + } + } + } + + // Get original image dimensions + list($orig_width, $orig_height) = getimagesize($dest_path); + + /* --- CREATE THUMBNAIL --- */ + $thumbnail_width = 200; + $thumbnail_height = 200; $thumb_img = imagecreatetruecolor($thumbnail_width, $thumbnail_height); imagecopyresampled($thumb_img, $src_img, 0, 0, 0, 0, - $thumbnail_width, $thumbnail_height, - $orig_width, $orig_height); - + $thumbnail_width, $thumbnail_height, $orig_width, $orig_height); $thumbnail_file_name = 'thumbnail_' . $file_reference_name; $thumb_path = $upload_file_dir . $thumbnail_file_name; - // Save thumbnail to disk switch ($file_extension) { case 'jpg': case 'jpeg': @@ -111,44 +149,39 @@ if (isset($_POST['upload_files'])) { imagewebp($thumb_img, $thumb_path); break; } - imagedestroy($thumb_img); + mysqli_query($mysqli, "UPDATE files SET file_has_thumbnail = 1 WHERE file_id = $file_id"); - mysqli_query($mysqli,"UPDATE files SET file_has_thumbnail = 1 WHERE file_id = $file_id"); - - // ------------------------- - // CREATE OPTIMIZED PREVIEW IMAGE - // ------------------------- + /* --- CREATE OPTIMIZED PREVIEW IMAGE --- */ + $preview_max_width = 1200; + $preview_max_height = 1200; $aspect_ratio = $orig_width / $orig_height; + if ($orig_width <= $preview_max_width && $orig_height <= $preview_max_height) { - $preview_new_width = $orig_width; + $preview_new_width = $orig_width; $preview_new_height = $orig_height; } elseif ($aspect_ratio > 1) { // Wider than tall - $preview_new_width = $preview_max_width; + $preview_new_width = $preview_max_width; $preview_new_height = (int)($preview_max_width / $aspect_ratio); } else { // Taller or square $preview_new_height = $preview_max_height; - $preview_new_width = (int)($preview_max_height * $aspect_ratio); + $preview_new_width = (int)($preview_max_height * $aspect_ratio); } $preview_img = imagecreatetruecolor($preview_new_width, $preview_new_height); imagecopyresampled($preview_img, $src_img, 0, 0, 0, 0, - $preview_new_width, $preview_new_height, - $orig_width, $orig_height); - + $preview_new_width, $preview_new_height, $orig_width, $orig_height); $preview_file_name = 'preview_' . $file_reference_name; $preview_path = $upload_file_dir . $preview_file_name; switch ($file_extension) { case 'jpg': case 'jpeg': - // Lower quality for optimization (70 is example) imagejpeg($preview_img, $preview_path, 70); break; case 'png': - // Higher compression level (0-9), 7 is an example imagepng($preview_img, $preview_path, 7); break; case 'gif': @@ -158,25 +191,24 @@ if (isset($_POST['upload_files'])) { imagewebp($preview_img, $preview_path, 70); break; } - imagedestroy($preview_img); imagedestroy($src_img); - mysqli_query($mysqli,"UPDATE files SET file_has_preview = 1 WHERE file_id = $file_id"); + mysqli_query($mysqli, "UPDATE files SET file_has_preview = 1 WHERE file_id = $file_id"); } } - // Logging + // Log the file upload action logAction("File", "Upload", "$session_name uploaded file $file_name", $client_id, $file_id); - $_SESSION['alert_message'] = "Uploaded file $file_name"; } else { $_SESSION['alert_type'] = 'error'; - $_SESSION['alert_message'] = 'There was an error moving the file to upload directory. Please make sure the upload directory is writable by web server.'; + $_SESSION['alert_message'] = 'There was an error processing the file upload. Please ensure the upload directory is writable by the web server.'; } } - // Redirect at the end, after processing all files + // Redirect back to the previous page after processing header("Location: " . $_SERVER["HTTP_REFERER"]); + exit; } if (isset($_POST['rename_file'])) {