diff --git a/blocksuite/affine/shared/src/__tests__/utils/url.unit.spec.ts b/blocksuite/affine/shared/src/__tests__/utils/url.unit.spec.ts index 80d80469be..797d14f2c7 100644 --- a/blocksuite/affine/shared/src/__tests__/utils/url.unit.spec.ts +++ b/blocksuite/affine/shared/src/__tests__/utils/url.unit.spec.ts @@ -80,4 +80,8 @@ describe('isValidUrl: determining whether a URL is valid is very complicated', ( // See also https://stackoverflow.com/questions/9238640/how-long-can-a-tld-possibly-be#:~:text=Longest%20TLD%20up%20to%20date,17%20when%20decoded%20%5Bverm%C3%B6gensberatung%5D. expect(isValidUrl('example.xn--vermgensberatung-pwb')).toEqual(false); }); + + test('should allow ip address url when origin is same', () => { + expect(isValidUrl('http://127.0.0.1', 'http://127.0.0.1')).toEqual(true); + }); }); diff --git a/blocksuite/affine/shared/src/utils/url.ts b/blocksuite/affine/shared/src/utils/url.ts index 9265195933..df96797af4 100644 --- a/blocksuite/affine/shared/src/utils/url.ts +++ b/blocksuite/affine/shared/src/utils/url.ts @@ -11,6 +11,9 @@ const ALLOWED_SCHEMES = new Set([ // https://publicsuffix.org/ const TLD_REGEXP = /(?:\.[a-zA-Z]+)?(\.[a-zA-Z]{2,})$/; +const IPV4_ADDR_REGEXP = + /^(25[0-5]|2[0-4]\d|[01]?\d\d?)(\.(25[0-5]|2[0-4]\d|[01]?\d\d?)){3}$/; + const toURL = (str: string) => { try { if (!URL.canParse(str)) return null; @@ -21,16 +24,20 @@ const toURL = (str: string) => { } }; -function resolveURL(str: string) { +function resolveURL(str: string, baseUrl: string, padded = false) { const url = toURL(str); if (!url) return null; const protocol = url.protocol.substring(0, url.protocol.length - 1); const hostname = url.hostname; + const origin = url.origin; let allowed = ALLOWED_SCHEMES.has(protocol); if (allowed && hostname.includes('.')) { - allowed = TLD_REGEXP.test(hostname); + allowed = + origin === baseUrl || + TLD_REGEXP.test(hostname) || + (padded ? false : IPV4_ADDR_REGEXP.test(hostname)); } return { url, allowed }; @@ -68,10 +75,10 @@ export function normalizeUrl(str: string) { * * For more detail see https://www.ietf.org/rfc/rfc1738.txt */ -export function isValidUrl(str: string) { +export function isValidUrl(str: string, baseUrl = location.origin) { str = str.trim(); - let result = resolveURL(str); + let result = resolveURL(str, baseUrl); if (result && !result.allowed) return false; @@ -80,7 +87,7 @@ export function isValidUrl(str: string) { if (!hasScheme) { const dotIdx = str.indexOf('.'); if (dotIdx > 0 && dotIdx < str.length - 1) { - result = resolveURL(`https://${str}`); + result = resolveURL(`https://${str}`, baseUrl, true); } } }