Skip to content

Commit

Permalink
fix(rtf msword support): Add support for rtfs identified as msword (#388
Browse files Browse the repository at this point in the history
)
  • Loading branch information
mdial89f authored Feb 15, 2024
1 parent 4d157db commit 424107e
Showing 1 changed file with 43 additions and 40 deletions.
83 changes: 43 additions & 40 deletions src/services/uploads/src/clamav.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import fs from "fs";
import asyncfs from "fs/promises";
import * as constants from "./constants";
import * as utils from "./utils";
import {FileExtension, MimeType, fileTypeFromFile} from 'file-type';
import { FileExtension, MimeType, fileTypeFromFile } from "file-type";

const s3Client: S3Client = new S3Client();

Expand Down Expand Up @@ -207,33 +207,31 @@ export const uploadAVDefinitions = async (): Promise<void[]> => {
*
* @param pathToFile Path in the filesystem where the file is stored.
*/
export const scanLocalFile = async (pathToFile: string, contentType: string | undefined): Promise<string | null> => {
export const scanLocalFile = async (
pathToFile: string,
contentType: string | undefined
): Promise<string | null> => {
try {
if(!contentType){
if (!contentType) {
utils.generateSystemMessage("FAILURE - EXTENSION UNKNOWN");
return constants.STATUS_UNKNOWN_EXTENSION;
}
let detectedContentType = await getFileTypeFromContents(pathToFile);
if(detectedContentType){
console.log(`File declared extension: ${contentType}`);
console.log(`File detected extension: ${detectedContentType}`)
let same = areMimeTypesEquivalent(contentType, detectedContentType)
if(!same){
utils.generateSystemMessage(`FAILURE - FILE EXTENSION DOES NOT MATCH FILE CONTENTS`);
return constants.STATUS_EXTENSION_MISMATCH_FILE
if (detectedContentType) {
console.log(`File declared extension: ${contentType}`);
console.log(`File detected extension: ${detectedContentType}`);
let same = areMimeTypesEquivalent(contentType, detectedContentType);
if (!same) {
utils.generateSystemMessage(
`FAILURE - FILE EXTENSION DOES NOT MATCH FILE CONTENTS`
);
return constants.STATUS_EXTENSION_MISMATCH_FILE;
}
}

const avResult: SpawnSyncReturns<Buffer> = spawnSync(
constants.PATH_TO_CLAMAV,
[
"--stdout",
"-v",
"-a",
"-d",
constants.FRESHCLAM_WORK_DIR,
pathToFile,
]
["--stdout", "-v", "-a", "-d", constants.FRESHCLAM_WORK_DIR, pathToFile]
);

// status 1 means that the file is infected.
Expand All @@ -259,42 +257,47 @@ export const scanLocalFile = async (pathToFile: string, contentType: string | un
}
};

async function getFileTypeFromContents(filePath: string): Promise<MimeType | null> {
async function getFileTypeFromContents(
filePath: string
): Promise<MimeType | null> {
try {
const fileBuffer = await fs.promises.readFile(filePath);
const fileBuffer = await fs.promises.readFile(filePath);

// Get the file type from its contents
const type = await fileTypeFromFile(filePath);
// Get the file type from its contents
const type = await fileTypeFromFile(filePath);

if (!type) {
console.log('Could not determine file type.');
return null;
}
console.log(`File type is ${type.mime} with extension ${type.ext}`);
return type.mime
if (!type) {
console.log("Could not determine file type.");
return null;
}
console.log(`File type is ${type.mime} with extension ${type.ext}`);
return type.mime;
} catch (error) {
console.error('Error reading file:', error);
return null
console.error("Error reading file:", error);
return null;
}
}

function areMimeTypesEquivalent(mime1: string, mime2: string): boolean {
const equivalentTypes: { [key: string]: Set<string> } = {
'application/rtf': new Set(['text/rtf']),
'application/vnd.ms-excel': new Set(['application/x-cfb']),
'application/vnd.ms-powerpoint': new Set(['application/x-cfb']),
'application/msword': new Set(['application/x-cfb'])
"application/rtf": new Set(["text/rtf"]),
"application/vnd.ms-excel": new Set(["application/x-cfb"]),
"application/vnd.ms-powerpoint": new Set(["application/x-cfb"]),
"application/msword": new Set(["application/x-cfb", "application/rtf"]),
};
mime1 = mime1.toLowerCase();
mime2 = mime2.toLowerCase();
if (mime1 === mime2) {
return true;
return true;
}
for (const baseType in equivalentTypes) {
const equivalents = equivalentTypes[baseType];
if ((mime1 === baseType && equivalents.has(mime2)) || (mime2 === baseType && equivalents.has(mime1))) {
return true;
}
const equivalents = equivalentTypes[baseType];
if (
(mime1 === baseType && equivalents.has(mime2)) ||
(mime2 === baseType && equivalents.has(mime1))
) {
return true;
}
}
return false;
}
}

0 comments on commit 424107e

Please sign in to comment.