import { createBlob, createRepBlob, uploadSingleFile } from "../../../actions/azurestorage"; import nextConnect from "next-connect"; import middleware from "../middleware/middleware"; import { consoleLogger } from "../../../actions/core/logger"; import { fileTypeFromBuffer } from "file-type"; import fs from "fs"; import path from "path"; const FILENAME_ALLOWED = /^[A-Za-z0-9 ._\-:()—']+$/; function validateFilenameServer(originalFilename) { const name = path.basename(originalFilename || ""); if (!name) return { ok: false, reason: "Empty filename" }; if (name.includes("#")) return { ok: false, reason: "Filename contains #" }; if (/[<>"/\\|?*]/.test(name)) return { ok: false, reason: "Filename contains reserved characters" }; if (!FILENAME_ALLOWED.test(name)) return { ok: false, reason: "Filename contains invalid characters" }; if (name === "." || name === "..") return { ok: false, reason: "Invalid filename" }; return { ok: true, name }; } const ApiProxy = nextConnect(); ApiProxy.use(middleware); ApiProxy.post(async (req, res) => { var checkHash = req.query.hash; const containerID = req.body.containerID[0]; const casefolderID = req.body.casefolderID[0]; console.log("there are files:", Object.keys(req.files).length); // Add other mimetypes here const allowedMimeTypes = [ "application/pdf", "application/msword", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "image/tiff", "image/jpeg", "application/zip", "image/png", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" ]; var allowedFilesFormData = {}; var invalidFiles = []; // To store the names of invalid files for (const [fileName, fileDetails] of Object.entries(req.files)) { const file = fileDetails[0]; const filePath = file.path; // validate ORIGINAL filename from upload const fnCheck = validateFilenameServer(file.originalFilename); if (!fnCheck.ok) { console.log( `File ${file.originalFilename} rejected: ${fnCheck.reason}` ); invalidFiles.push(`${file.originalFilename} - Invalid filename`); continue; // do not process further } // Check the MIME type from file headers const fileMimeType = file.headers["content-type"]; if (allowedMimeTypes.includes(fileMimeType)) { // Check file signature (magic number) using file-type const buffer = fs.readFileSync(filePath); try { const type = await fileTypeFromBuffer(buffer); // Correct usage of fileTypeFromBuffer console.log("checking mime type ", type); if (type && allowedMimeTypes.includes(type.mime)) { // If the MIME type from the file signature matches the allowed list allowedFilesFormData[fileName] = fileDetails.map( (file) => ({ fieldName: file.fieldName, originalFilename: file.originalFilename, path: file.path, size: file.size, headers: file.headers, contentType: fileMimeType }) ); } else { console.log( `\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n\nFile ${fileName} has an invalid MIME type based on its content.\n\n\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\` ); invalidFiles.push(fileName); // Track invalid file } } catch (error) { console.log( `Error reading file ${fileName} for MIME type validation`, error ); } } else { console.log( `\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n\nFile ${fileName} has an unsupported MIME type: ${fileMimeType}\n\n\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\` ); invalidFiles.push(fileName); // Track invalid file } } try { const data = await uploadSingleFile( allowedFilesFormData, containerID, casefolderID ); return res.status(200).json({ data, invalidFiles }); } catch (error) { consoleLogger(error); return res.status(500).json({ error: "Failed to upload files" }); } }); export const config = { api: { bodyParser: false } }; export default ApiProxy;