Added support for a number of further file types and file detection methods.
This commit is contained in:
parent
9829491c4c
commit
8d3836cb16
@ -13,7 +13,7 @@ import Stream from "./Stream";
|
|||||||
* to extract them where possible.
|
* to extract them where possible.
|
||||||
*/
|
*/
|
||||||
const FILE_SIGNATURES = {
|
const FILE_SIGNATURES = {
|
||||||
"Pictures": [
|
"Images": [
|
||||||
{
|
{
|
||||||
name: "JPEG Image",
|
name: "JPEG Image",
|
||||||
extension: "jpg",
|
extension: "jpg",
|
||||||
@ -51,7 +51,165 @@ const FILE_SIGNATURES = {
|
|||||||
},
|
},
|
||||||
extractor: null
|
extractor: null
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "WEBP Image",
|
||||||
|
extension: "webp",
|
||||||
|
mime: "image/webp",
|
||||||
|
description: "",
|
||||||
|
signature: {
|
||||||
|
8: 0x57,
|
||||||
|
9: 0x45,
|
||||||
|
10: 0x42,
|
||||||
|
11: 0x50
|
||||||
|
},
|
||||||
|
extractor: null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "TIFF Image",
|
||||||
|
extension: "tif",
|
||||||
|
mime: "image/tiff",
|
||||||
|
description: "",
|
||||||
|
signature: [
|
||||||
|
{
|
||||||
|
0: 0x49,
|
||||||
|
1: 0x49,
|
||||||
|
2: 0x2a,
|
||||||
|
3: 0x0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
0: 0x4d,
|
||||||
|
1: 0x4d,
|
||||||
|
2: 0x0,
|
||||||
|
3: 0x2a
|
||||||
|
}
|
||||||
|
],
|
||||||
|
extractor: null
|
||||||
|
}, /*
|
||||||
|
{
|
||||||
|
name: " Image",
|
||||||
|
extension: "",
|
||||||
|
mime: "image/",
|
||||||
|
description: "",
|
||||||
|
signature: {
|
||||||
|
0: 0x,
|
||||||
|
1: 0x,
|
||||||
|
2: 0x,
|
||||||
|
3: 0x
|
||||||
|
},
|
||||||
|
extractor: null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: " Image",
|
||||||
|
extension: "",
|
||||||
|
mime: "image/",
|
||||||
|
description: "",
|
||||||
|
signature: {
|
||||||
|
0: 0x,
|
||||||
|
1: 0x,
|
||||||
|
2: 0x,
|
||||||
|
3: 0x
|
||||||
|
},
|
||||||
|
extractor: null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: " Image",
|
||||||
|
extension: "",
|
||||||
|
mime: "image/",
|
||||||
|
description: "",
|
||||||
|
signature: {
|
||||||
|
0: 0x,
|
||||||
|
1: 0x,
|
||||||
|
2: 0x,
|
||||||
|
3: 0x
|
||||||
|
},
|
||||||
|
extractor: null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: " Image",
|
||||||
|
extension: "",
|
||||||
|
mime: "image/",
|
||||||
|
description: "",
|
||||||
|
signature: {
|
||||||
|
0: 0x,
|
||||||
|
1: 0x,
|
||||||
|
2: 0x,
|
||||||
|
3: 0x
|
||||||
|
},
|
||||||
|
extractor: null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: " Image",
|
||||||
|
extension: "",
|
||||||
|
mime: "image/",
|
||||||
|
description: "",
|
||||||
|
signature: {
|
||||||
|
0: 0x,
|
||||||
|
1: 0x,
|
||||||
|
2: 0x,
|
||||||
|
3: 0x
|
||||||
|
},
|
||||||
|
extractor: null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: " Image",
|
||||||
|
extension: "",
|
||||||
|
mime: "image/",
|
||||||
|
description: "",
|
||||||
|
signature: {
|
||||||
|
0: 0x,
|
||||||
|
1: 0x,
|
||||||
|
2: 0x,
|
||||||
|
3: 0x
|
||||||
|
},
|
||||||
|
extractor: null
|
||||||
|
},*/
|
||||||
|
],
|
||||||
|
"Video": [
|
||||||
|
{
|
||||||
|
name: "WEBM",
|
||||||
|
extension: "webm",
|
||||||
|
mime: "video/webm",
|
||||||
|
description: "",
|
||||||
|
signature: {
|
||||||
|
0: 0x1a,
|
||||||
|
1: 0x45,
|
||||||
|
2: 0xdf,
|
||||||
|
3: 0xa3
|
||||||
|
},
|
||||||
|
extractor: null
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"Audio": [
|
||||||
|
{
|
||||||
|
name: "WAV",
|
||||||
|
extension: "wav",
|
||||||
|
mime: "audio/x-wav",
|
||||||
|
description: "",
|
||||||
|
signature: {
|
||||||
|
0: 0x52,
|
||||||
|
1: 0x49,
|
||||||
|
2: 0x46,
|
||||||
|
3: 0x46,
|
||||||
|
8: 0x57,
|
||||||
|
9: 0x41,
|
||||||
|
10: 0x56,
|
||||||
|
11: 0x45
|
||||||
|
},
|
||||||
|
extractor: null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "OGG",
|
||||||
|
extension: "ogg",
|
||||||
|
mime: "audio/ogg",
|
||||||
|
description: "",
|
||||||
|
signature: {
|
||||||
|
0: 0x4f,
|
||||||
|
1: 0x67,
|
||||||
|
2: 0x67,
|
||||||
|
3: 0x53
|
||||||
|
},
|
||||||
|
extractor: null
|
||||||
|
},
|
||||||
],
|
],
|
||||||
"Documents": [
|
"Documents": [
|
||||||
{
|
{
|
||||||
@ -103,13 +261,31 @@ const FILE_SIGNATURES = {
|
|||||||
/**
|
/**
|
||||||
* Checks whether a signature matches a buffer.
|
* Checks whether a signature matches a buffer.
|
||||||
*
|
*
|
||||||
* @param {Object} sig - A dictionary of offsets with values assigned to them. These
|
* @param {Object|Object[]} sig - A dictionary of offsets with values assigned to them.
|
||||||
* values can be numbers for static checks, arrays of potential valid matches, or
|
* These values can be numbers for static checks, arrays of potential valid matches,
|
||||||
* bespoke functions to check the validity of the buffer value at that offset.
|
* or bespoke functions to check the validity of the buffer value at that offset.
|
||||||
* @param {Uint8Array} buf
|
* @param {Uint8Array} buf
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
function signatureMatches(sig, buf) {
|
function signatureMatches(sig, buf) {
|
||||||
|
if (sig instanceof Array) {
|
||||||
|
return sig.reduce((acc, s) => acc || bytesMatch(s, buf), false);
|
||||||
|
} else {
|
||||||
|
return bytesMatch(sig, buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether a set of bytes match the given buffer.
|
||||||
|
*
|
||||||
|
* @param {Object} sig - A dictionary of offsets with values assigned to them.
|
||||||
|
* These values can be numbers for static checks, arrays of potential valid matches,
|
||||||
|
* or bespoke functions to check the validity of the buffer value at that offset.
|
||||||
|
* @param {Uint8Array} buf
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
function bytesMatch(sig, buf) {
|
||||||
for (const offset in sig) {
|
for (const offset in sig) {
|
||||||
switch (typeof sig[offset]) {
|
switch (typeof sig[offset]) {
|
||||||
case "number": // Static check
|
case "number": // Static check
|
||||||
@ -165,34 +341,6 @@ export function detectFileType(buf) {
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if (buf[0] === 0xFF && buf[1] === 0xD8 && buf[2] === 0xFF) {
|
|
||||||
return {
|
|
||||||
ext: "jpg",
|
|
||||||
mime: "image/jpeg"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buf[0] === 0x89 && buf[1] === 0x50 && buf[2] === 0x4E && buf[3] === 0x47) {
|
|
||||||
return {
|
|
||||||
ext: "png",
|
|
||||||
mime: "image/png"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buf[0] === 0x47 && buf[1] === 0x49 && buf[2] === 0x46) {
|
|
||||||
return {
|
|
||||||
ext: "gif",
|
|
||||||
mime: "image/gif"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buf[8] === 0x57 && buf[9] === 0x45 && buf[10] === 0x42 && buf[11] === 0x50) {
|
|
||||||
return {
|
|
||||||
ext: "webp",
|
|
||||||
mime: "image/webp"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// needs to be before `tif` check
|
// needs to be before `tif` check
|
||||||
if (((buf[0] === 0x49 && buf[1] === 0x49 && buf[2] === 0x2A && buf[3] === 0x0) || (buf[0] === 0x4D && buf[1] === 0x4D && buf[2] === 0x0 && buf[3] === 0x2A)) && buf[8] === 0x43 && buf[9] === 0x52) {
|
if (((buf[0] === 0x49 && buf[1] === 0x49 && buf[2] === 0x2A && buf[3] === 0x0) || (buf[0] === 0x4D && buf[1] === 0x4D && buf[2] === 0x0 && buf[3] === 0x2A)) && buf[8] === 0x43 && buf[9] === 0x52) {
|
||||||
return {
|
return {
|
||||||
@ -237,13 +385,6 @@ export function detectFileType(buf) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf[0] === 0x50 && buf[1] === 0x4B && (buf[2] === 0x3 || buf[2] === 0x5 || buf[2] === 0x7) && (buf[3] === 0x4 || buf[3] === 0x6 || buf[3] === 0x8)) {
|
|
||||||
return {
|
|
||||||
ext: "zip",
|
|
||||||
mime: "application/zip"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buf[257] === 0x75 && buf[258] === 0x73 && buf[259] === 0x74 && buf[260] === 0x61 && buf[261] === 0x72) {
|
if (buf[257] === 0x75 && buf[258] === 0x73 && buf[259] === 0x74 && buf[260] === 0x61 && buf[261] === 0x72) {
|
||||||
return {
|
return {
|
||||||
ext: "tar",
|
ext: "tar",
|
||||||
@ -315,13 +456,6 @@ export function detectFileType(buf) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf[0] === 0x1A && buf[1] === 0x45 && buf[2] === 0xDF && buf[3] === 0xA3) {
|
|
||||||
return {
|
|
||||||
ext: "webm",
|
|
||||||
mime: "video/webm"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buf[0] === 0x0 && buf[1] === 0x0 && buf[2] === 0x0 && buf[3] === 0x14 && buf[4] === 0x66 && buf[5] === 0x74 && buf[6] === 0x79 && buf[7] === 0x70) {
|
if (buf[0] === 0x0 && buf[1] === 0x0 && buf[2] === 0x0 && buf[3] === 0x14 && buf[4] === 0x66 && buf[5] === 0x74 && buf[6] === 0x79 && buf[7] === 0x70) {
|
||||||
return {
|
return {
|
||||||
ext: "mov",
|
ext: "mov",
|
||||||
@ -364,13 +498,6 @@ export function detectFileType(buf) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf[0] === 0x4F && buf[1] === 0x67 && buf[2] === 0x67 && buf[3] === 0x53) {
|
|
||||||
return {
|
|
||||||
ext: "ogg",
|
|
||||||
mime: "audio/ogg"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buf[0] === 0x66 && buf[1] === 0x4C && buf[2] === 0x61 && buf[3] === 0x43) {
|
if (buf[0] === 0x66 && buf[1] === 0x4C && buf[2] === 0x61 && buf[3] === 0x43) {
|
||||||
return {
|
return {
|
||||||
ext: "flac",
|
ext: "flac",
|
||||||
@ -378,13 +505,6 @@ export function detectFileType(buf) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf[0] === 0x52 && buf[1] === 0x49 && buf[2] === 0x46 && buf[3] === 0x46 && buf[8] === 0x57 && buf[9] === 0x41 && buf[10] === 0x56 && buf[11] === 0x45) {
|
|
||||||
return {
|
|
||||||
ext: "wav",
|
|
||||||
mime: "audio/x-wav"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buf[0] === 0x23 && buf[1] === 0x21 && buf[2] === 0x41 && buf[3] === 0x4D && buf[4] === 0x52 && buf[5] === 0x0A) {
|
if (buf[0] === 0x23 && buf[1] === 0x21 && buf[2] === 0x41 && buf[3] === 0x4D && buf[4] === 0x52 && buf[5] === 0x0A) {
|
||||||
return {
|
return {
|
||||||
ext: "amr",
|
ext: "amr",
|
||||||
@ -392,20 +512,6 @@ export function detectFileType(buf) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf[0] === 0x25 && buf[1] === 0x50 && buf[2] === 0x44 && buf[3] === 0x46) {
|
|
||||||
return {
|
|
||||||
ext: "pdf",
|
|
||||||
mime: "application/pdf"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buf[0] === 0x4D && buf[1] === 0x5A) {
|
|
||||||
return {
|
|
||||||
ext: "exe",
|
|
||||||
mime: "application/x-msdownload"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((buf[0] === 0x43 || buf[0] === 0x46) && buf[1] === 0x57 && buf[2] === 0x53) {
|
if ((buf[0] === 0x43 || buf[0] === 0x46) && buf[1] === 0x57 && buf[2] === 0x53) {
|
||||||
return {
|
return {
|
||||||
ext: "swf",
|
ext: "swf",
|
||||||
|
@ -39,7 +39,7 @@ class DetectFileType extends Operation {
|
|||||||
if (!types.length) {
|
if (!types.length) {
|
||||||
return "Unknown file type. Have you tried checking the entropy of this data to determine whether it might be encrypted or compressed?";
|
return "Unknown file type. Have you tried checking the entropy of this data to determine whether it might be encrypted or compressed?";
|
||||||
} else {
|
} else {
|
||||||
let output;
|
let output = "";
|
||||||
|
|
||||||
types.forEach(type => {
|
types.forEach(type => {
|
||||||
output += "File extension: " + type.extension + "\n" +
|
output += "File extension: " + type.extension + "\n" +
|
||||||
|
@ -9,7 +9,7 @@ import { fromHex } from "../lib/Hex";
|
|||||||
import Operation from "../Operation";
|
import Operation from "../Operation";
|
||||||
import OperationError from "../errors/OperationError";
|
import OperationError from "../errors/OperationError";
|
||||||
import Utils from "../Utils";
|
import Utils from "../Utils";
|
||||||
import Magic from "../lib/Magic";
|
import { detectFileType } from "../lib/FileType";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PlayMedia operation
|
* PlayMedia operation
|
||||||
@ -66,8 +66,8 @@ class PlayMedia extends Operation {
|
|||||||
|
|
||||||
|
|
||||||
// Determine file type
|
// Determine file type
|
||||||
const type = Magic.magicFileType(input);
|
const types = detectFileType(input);
|
||||||
if (!(type && /^audio|video/.test(type.mime))) {
|
if (!(types && types.length && /^audio|video/.test(types[0].mime))) {
|
||||||
throw new OperationError("Invalid or unrecognised file type");
|
throw new OperationError("Invalid or unrecognised file type");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,15 +84,15 @@ class PlayMedia extends Operation {
|
|||||||
async present(data) {
|
async present(data) {
|
||||||
if (!data.length) return "";
|
if (!data.length) return "";
|
||||||
|
|
||||||
const type = Magic.magicFileType(data);
|
const types = detectFileType(data);
|
||||||
const matches = /^audio|video/.exec(type.mime);
|
const matches = /^audio|video/.exec(types[0].mime);
|
||||||
if (!matches) {
|
if (!matches) {
|
||||||
throw new OperationError("Invalid file type");
|
throw new OperationError("Invalid file type");
|
||||||
}
|
}
|
||||||
const dataURI = `data:${type.mime};base64,${toBase64(data)}`;
|
const dataURI = `data:${types[0].mime};base64,${toBase64(data)}`;
|
||||||
const element = matches[0];
|
const element = matches[0];
|
||||||
|
|
||||||
let html = `<${element} src='${dataURI}' type='${type.mime}' controls>`;
|
let html = `<${element} src='${dataURI}' type='${types[0].mime}' controls>`;
|
||||||
html += "<p>Unsupported media type.</p>";
|
html += "<p>Unsupported media type.</p>";
|
||||||
html += `</${element}>`;
|
html += `</${element}>`;
|
||||||
return html;
|
return html;
|
||||||
|
Loading…
Reference in New Issue
Block a user