fix: Improve performance of base64 detection regex
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
import { Blob } from "buffer";
|
import { Blob } from "buffer";
|
||||||
import { Readable } from "stream";
|
import { Readable } from "stream";
|
||||||
import { PresignedPost } from "aws-sdk/clients/s3";
|
import { PresignedPost } from "aws-sdk/clients/s3";
|
||||||
|
import { isBase64Url } from "@shared/utils/urls";
|
||||||
import env from "@server/env";
|
import env from "@server/env";
|
||||||
import Logger from "@server/logging/Logger";
|
import Logger from "@server/logging/Logger";
|
||||||
import fetch from "@server/utils/fetch";
|
import fetch from "@server/utils/fetch";
|
||||||
@@ -132,7 +133,7 @@ export default abstract class BaseStorage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let buffer, contentType;
|
let buffer, contentType;
|
||||||
const match = url.match(/data:(.*);base64,(.*)/);
|
const match = isBase64Url(url);
|
||||||
|
|
||||||
if (match) {
|
if (match) {
|
||||||
contentType = match[1];
|
contentType = match[1];
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import * as urlsUtils from "./urls";
|
import * as urlsUtils from "./urls";
|
||||||
import { urlRegex } from "./urls";
|
import { urlRegex } from "./urls";
|
||||||
|
|
||||||
describe("IsUrl Method", () => {
|
describe("isUrl", () => {
|
||||||
it("should return false for invalid url", () => {
|
it("should return false for invalid url", () => {
|
||||||
expect(urlsUtils.isUrl("")).toBe(false);
|
expect(urlsUtils.isUrl("")).toBe(false);
|
||||||
expect(urlsUtils.isUrl("#invalidurl")).toBe(false);
|
expect(urlsUtils.isUrl("#invalidurl")).toBe(false);
|
||||||
@@ -19,7 +19,33 @@ describe("IsUrl Method", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("isInternalUrl Method", () => {
|
describe("isBase64Url", () => {
|
||||||
|
it("should return false for invalid url", () => {
|
||||||
|
expect(urlsUtils.isBase64Url("")).toBe(false);
|
||||||
|
expect(urlsUtils.isBase64Url("#invalidurl")).toBe(false);
|
||||||
|
expect(urlsUtils.isBase64Url("http://example.com")).toBe(false);
|
||||||
|
expect(urlsUtils.isBase64Url("https://www.example.com")).toBe(false);
|
||||||
|
expect(urlsUtils.isBase64Url("seafile://openfile")).toBe(false);
|
||||||
|
expect(urlsUtils.isBase64Url("figma://launch")).toBe(false);
|
||||||
|
expect(urlsUtils.isBase64Url("outline:https://getoutline.com")).toBe(false);
|
||||||
|
expect(urlsUtils.isBase64Url("://")).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return true for valid urls", () => {
|
||||||
|
expect(
|
||||||
|
urlsUtils.isBase64Url(
|
||||||
|
"data:image/png;base64,R0lGODlhPQBEAPeoAJosM//AwO/AwHVYZ/z595kzAP/s7P+goOXMv8+fhw/v739/f+8PD98fH/8mJl+fn/9ZWb8/PzWlwv///6wWGbImAPgTEMImIN9gUFCEm/gDALULDN8PAD6atYdCTX9gUNKlj8wZAKUsAOzZz+UMAOsJAP/Z2ccMDA8PD/95eX5NWvsJCOVNQPtfX/8zM8+QePLl38MGBr8JCP+zs9myn/8GBqwpAP/GxgwJCPny78lzYLgjAJ8vAP9fX/+MjMUcAN8zM/9wcM8ZGcATEL+QePdZWf/29uc/P9cmJu9MTDImIN+/r7+/vz8/P8VNQGNugV8AAF9fX8swMNgTAFlDOICAgPN"
|
||||||
|
)
|
||||||
|
).toBeTruthy();
|
||||||
|
expect(
|
||||||
|
urlsUtils.isBase64Url(
|
||||||
|
"data:image/gif;base64,npkM+fOqD6DDj1aZpITp0dtGCDhr+fVuCu3zlg49ijaokTZTo27uG7Gjn2P+hI8+PDPERoUB318bWbfAJ5sUNFcuGRTYUqV/3ogfXp1rWlMc6awJjiAAd2fm4ogXjz56aypOoIde4OE5u/F9x199dlXnnGiHZWEYbGpsAEA3QXYnHwEFliKAgswgJ8LPeiUXGwedCAKABACCN+EA1pYIIYaFlcDhytd51sGAJbo3onOpajiihlO92KHGaUXGwWjUBChjSPiWJuOO/LYIm4v1tXfE6J4gCSJEZ7YgRYUNrkji9P55sF/ogxw5ZkSqIDaZBV6aSGYq/lGZplndkckZ98xoICbTcIJGQAZc"
|
||||||
|
)
|
||||||
|
).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("isInternalUrl", () => {
|
||||||
it("should return false if empty string", () => {
|
it("should return false if empty string", () => {
|
||||||
expect(urlsUtils.isInternalUrl("")).toBe(false);
|
expect(urlsUtils.isInternalUrl("")).toBe(false);
|
||||||
});
|
});
|
||||||
@@ -29,7 +55,7 @@ describe("isInternalUrl Method", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("isExternalUrl Method", () => {
|
describe("isExternalUrl", () => {
|
||||||
it("should return false if empty url", () => {
|
it("should return false if empty url", () => {
|
||||||
expect(urlsUtils.isExternalUrl("")).toBe(false);
|
expect(urlsUtils.isExternalUrl("")).toBe(false);
|
||||||
});
|
});
|
||||||
@@ -39,7 +65,7 @@ describe("isExternalUrl Method", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("sanitizeUrl Method", () => {
|
describe("sanitizeUrl", () => {
|
||||||
it("should return undefined if not url", () => {
|
it("should return undefined if not url", () => {
|
||||||
expect(urlsUtils.sanitizeUrl(undefined)).toBeUndefined();
|
expect(urlsUtils.sanitizeUrl(undefined)).toBeUndefined();
|
||||||
expect(urlsUtils.sanitizeUrl(null)).toBeUndefined();
|
expect(urlsUtils.sanitizeUrl(null)).toBeUndefined();
|
||||||
|
|||||||
@@ -86,6 +86,17 @@ export function isExternalUrl(url: string) {
|
|||||||
return !!url && !isInternalUrl(url) && !url.startsWith(creatingUrlPrefix);
|
return !!url && !isInternalUrl(url) && !url.startsWith(creatingUrlPrefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns match if the given string is a base64 encoded url.
|
||||||
|
*
|
||||||
|
* @param url The url to check.
|
||||||
|
* @returns A RegExp match if the url is base64, false otherwise.
|
||||||
|
*/
|
||||||
|
export function isBase64Url(url: string) {
|
||||||
|
const match = url.match(/^(data:[a-z]+\/[^;]+;base64,(.*))/i);
|
||||||
|
return match ? match : false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For use in the editor, this function will ensure that a url is
|
* For use in the editor, this function will ensure that a url is
|
||||||
* potentially valid, and filter out unsupported and malicious protocols.
|
* potentially valid, and filter out unsupported and malicious protocols.
|
||||||
|
|||||||
Reference in New Issue
Block a user