file-type-checker
Version:
Detect and validate file types by their signatures (✨magic numbers✨)
92 lines (91 loc) • 4.33 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.validateFileType = void 0;
const core_1 = require("../core");
const utils_1 = require("../utils");
__exportStar(require("./audio"), exports);
__exportStar(require("./compressed"), exports);
__exportStar(require("./image"), exports);
__exportStar(require("./other"), exports);
__exportStar(require("./video"), exports);
/**
* Validates the requested file signature against a list of accepted file types
*
* @param file File content represents in Array<number> / ArrayBuffer / Uint8Array
* @param types A list of accepted file types
* @param options parameters for additional actions
*
* @returns {boolean} True if found a type signature from the accepted file types, otherwise false
*/
function validateFileType(file, types, options) {
var _a;
let typeExtensions = [];
const uniqueTypes = [
...new Set(types.map((type) => {
const normalizedType = type.split(".").join("").toUpperCase();
if (normalizedType === "7Z")
return `_${normalizedType}`;
return normalizedType;
})),
];
for (const type of uniqueTypes) {
if (!Object.prototype.hasOwnProperty.call(core_1.FileTypes, type))
throw new TypeError(`Type \`${type.toLowerCase()}\` is not supported. Please make sure that \`types\` list conatins only supported files`);
typeExtensions.push(type);
}
if (options &&
Object.prototype.hasOwnProperty.call(options, "chunkSize") &&
((_a = options === null || options === void 0 ? void 0 : options.chunkSize) !== null && _a !== void 0 ? _a : 0) <= 0)
throw new RangeError("chunkSize must be bigger than zero");
if (!options || !(options === null || options === void 0 ? void 0 : options.excludeSimilarTypes)) {
const similarTypes = addSimilarTypes(typeExtensions);
if (similarTypes.length > 0)
typeExtensions = typeExtensions.concat(similarTypes);
}
let acceptedSignatures = [];
const filesRequiredAdditionalCheck = [];
for (const type of typeExtensions) {
const extensionSignatures = core_1.FileTypes.getSignaturesByName(type);
acceptedSignatures = acceptedSignatures.concat(extensionSignatures);
if (core_1.FILE_TYPES_REQUIRED_ADDITIONAL_CHECK.includes(type.toLowerCase())) {
filesRequiredAdditionalCheck.push(core_1.FileTypes.getInfoByName(type));
}
}
const fileChunk = (0, utils_1.getFileChunk)(file, (options === null || options === void 0 ? void 0 : options.chunkSize) || 64);
const detectedSignature = core_1.FileTypes.detectSignature(fileChunk, acceptedSignatures);
if (!detectedSignature)
return false;
if (filesRequiredAdditionalCheck.length > 0) {
const detectedFilesForAdditionalCheck = filesRequiredAdditionalCheck.filter((frac) => frac.signatures.includes(detectedSignature));
if (detectedFilesForAdditionalCheck.length > 0) {
// Some files share the same signature. Additional check required
const detectedType = core_1.FileTypes.detectTypeByAdditionalCheck(fileChunk, detectedFilesForAdditionalCheck);
if (!detectedType)
return false;
return typeExtensions.some((df) => df.toLowerCase() === detectedType);
}
}
return true;
}
exports.validateFileType = validateFileType;
function addSimilarTypes(requiredTypes) {
if (requiredTypes.some((type) => type === "MP4"))
return ["M4V"];
if (requiredTypes.some((type) => type === "AAC"))
return ["M4A"];
return [];
}