Skip to content

Commit

Permalink
fix: fix mime check bug for jpeg/jpg and tiff (#291)
Browse files Browse the repository at this point in the history
  • Loading branch information
kunzms authored May 31, 2020
1 parent ea33ea1 commit 2760166
Showing 1 changed file with 26 additions and 38 deletions.
64 changes: 26 additions & 38 deletions src/services/assetService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,43 +21,36 @@ const supportedImageFormats = {
};

interface IMime {
mime: string;
types: string[];
pattern: (number|undefined)[];
}
}

// tslint:disable number-literal-format
// tslint:disable no-magic-numbers
const imageMimes: IMime[] = [
{
mime: "image/bmp",
pattern: [0x42, 0x4d],
},
{
mime: "image/png",
pattern: [0x89, 0x50, 0x4e, 0x47],
types: ["bmp"],
pattern: [0x42, 0x4d],
},
{
mime: "image/jpeg",
pattern: [0xff, 0xd8, 0xff, 0xdb],
types: ["png"],
pattern: [0x89, 0x50, 0x4e, 0x47],
},
{
mime: "image/jpg",
pattern: [0xff, 0xd8, 0xff, 0xf0, 0x00, 0xfe, 0xe1],
types: ["jpeg", "jpg"],
pattern: [0xff, 0xd8, 0xff],
},
{
mime: "image/tif",
pattern: [0x49, 0x49, 0x2a, 0x00],
types: ["tif", "tiff"],
pattern: [0x49, 0x49, 0x42, 0x00],
},
{
mime: "image/tiff",
pattern: [0x4d, 0x4d, 0x00, 0x2a],
},
{
mime: "application/pdf",
pattern: [0x25, 0x50, 0x44, 0x46, 0x2d],
types: ["pdf"],
pattern: [0x25, 0x50, 0x44, 0x46, 0x2d],
},
];
// We can expand this list @see https://mimesniff.spec.whatwg.org/#matching-an-image-type-pattern
const mimeBytesNeeded: number = (Math.max(...imageMimes.map((m) => m.pattern.length)) - 1);

/**
* @name - Asset Service
Expand Down Expand Up @@ -91,14 +84,14 @@ export class AssetService {

// eslint-disable-next-line
const extensionParts = fileNameParts[fileNameParts.length - 1].split(/[\?#]/);
let assetFormat = extensionParts[0];
let assetFormat = extensionParts[0].toLowerCase();

if (supportedImageFormats.hasOwnProperty(assetFormat.toLowerCase())) {
const mime = await this.getMimeType(filePath);
if (supportedImageFormats.hasOwnProperty(assetFormat)) {
const types = await this.getMimeType(filePath);

// If file was renamed/spoofed - fix file extension to true MIME type and show message
if (assetFormat !== mime) {
assetFormat = mime;
if (!types.includes(assetFormat)) {
assetFormat = types[0];
const corruptFileName = fileName.split("%2F").pop().replace(/%20/g, " ");
setTimeout(() => {
toast.info(`${strings.editorPage.assetWarning.incorrectFileExtension.attention} ${corruptFileName.toLocaleUpperCase()} ${strings.editorPage.assetWarning.incorrectFileExtension.text} ${corruptFileName.toLocaleUpperCase()}`);
Expand Down Expand Up @@ -141,31 +134,26 @@ export class AssetService {
}

// If extension of a file was spoofed, we fetch only first 4 bytes of the file and read MIME type
public static async getMimeType(uri: string): Promise<string> {
const numBytesNeeded: number = (Math.max(...imageMimes.map((m) => m.pattern.length)) - 1);
const first4bytes: Response = await fetch(uri, { headers: { range: `bytes=0-${numBytesNeeded}` } });
public static async getMimeType(uri: string): Promise<string[]> {
const first4bytes: Response = await fetch(uri, { headers: { range: `bytes=0-${mimeBytesNeeded}` } });
const arrayBuffer: ArrayBuffer = await first4bytes.arrayBuffer();
const blob = new Blob([new Uint8Array(arrayBuffer).buffer]);
const isMime = (bytes: Uint8Array, mime: IMime): boolean => {
return mime.pattern.every((p, i) => !p || bytes[i] === p);
};
const fileReader: FileReader = new FileReader();

const mimeType = new Promise<string>((resolve, reject) => {
return new Promise<string[]>((resolve, reject) => {
fileReader.onloadend = (e) => {
if (!e || !fileReader.result) { return; }
if (!e || !fileReader.result) {
return [];
}
const bytes: Uint8Array = new Uint8Array(fileReader.result as ArrayBuffer);
const fileMimes: string[] = imageMimes.map((mime) => {
if (isMime(bytes, mime)) {
return mime.mime;
}
});
const mime: string = fileMimes.filter((i) => i !== undefined)[0].split("/").pop();
resolve(mime);
const type: string[] = imageMimes.filter((mime) => isMime(bytes, mime))?.[0]?.types;
resolve(type || []);
};
fileReader.readAsArrayBuffer(blob);
});
return mimeType;
}

private assetProviderInstance: IAssetProvider;
Expand Down

0 comments on commit 2760166

Please sign in to comment.